Funkcja i dziedziczenie problem

0

Witam w czasie programowania natrafiłem na pewien problem nad którym się głowie i nie mogę wymyślić rozwiązania mam taki kod funkcji use klasy moc:

 
void moc::use(mastermind &game, bohater &hero, moc *power, rozgrywka &play){
    cout << "Który poziom mocy chcesz użyć?\n";
    int poziom;
    cin >> poziom;
    if(poziom>power->getPoziom() || poziom<=0){
        cout << "Nie masz mocy takiego poziomu\n";
    }
    else{
        cout << power->getMana(poziom-1) << endl;


        if(hero.getMana() < power->getMana(poziom-1)){
            cout << "Masz za malo many\n";
        }
        else{
            effect(poziom, game, hero, play);                     //effect z wszystkimi możliwymi argumentami
            hero.zmienMana(-power->getMana(poziom-1));
        }
    }
}

zęby nie utrudniać za bardzo klasa moc ma m.in takie funkcje i dziedziczą po niej klasy takie jak poniżej przedstawione:

 
class moc
{
public:
   void use(mastermind &game, bohater &hero, moc *power, rozgrywka &play)
   virtual void effect(mastermind &game, int poziom)
   virtual void effect(bohater &hero, int poziom)
   virtual void effect(rozgrywka &play)
}

class wiecejProb : public moc
{

public:
    virtual void effect(mastermind &game, int poziom);
};

class leczenie : public moc
{
public:
    virtual void effect(bohater &hero, int poziom);
};

class ucieczka : public moc
{
public:
    virtual void effect(rozgrywka &play);
};

czy da się stworzyć jakoś ładnie funkcje effect tak by przyjmowała wymagane argumenty i po utworzeniu np. obiektu wiecejProb wywołanie funkcja use wykorzystywała odpowiednią funkcje effect? bądź jak inaczej powinienem to rozwiązać?

0

a gdzie masz definicję funkcji: getMana, getPoziom() ??

0

Próbujesz niefortunnie połączyć wirtualizację z przesłanianiem. Zresztą na te chwilę cały ten mechanizm jest bezsensowny, bo w momencie wywołania tej metoty narzucasz, o którą jej wersję dokładnie chodzi. Patrząc po deklaracjach metody effect, każda kolejna, przesłonięta jej wersja znacznie różni się od pozostałych wersji. W takim wypadku lepiej byłoby zdefiniować osobne metody dla poszczególnych efektów.

0

a gdzie masz definicję funkcji: getMana, getPoziom() ??

Nie chciałem nadmiernie utrudniać wszystkiego zbędnym kodem poniżej cała klasa moc:

 
//moc.h
#ifndef MOC_H
#define MOC_H

#include <string>
#include "mastermind.h"
#include "bohater.h"
#include "rozgrywka.h"

using namespace std;

class rozgrywka;

class moc
{
private:
    string nazwa;
    string opis;
    int poziom;
    int maxpoziom;
    int *mana;
    int cena;
    int ulepszenie;
    int kosztulepszenia;
    int wzrostmany;
public:
    moc(string name, string description, int magic, int maxlevel, int cost, int upgrade, int upcost, int manacost);
    string getNazwa();
    string getOpis();
    int getMana(int a);
    int getPoziom();
    int getMaxPoziom();
    int getCena();
    int getUlepszenie();
    void zmienNazwa(string name);
    void zmienOpis(string description);
    void zmienPoziom(int level);
    void zmienCena(int price);
    void zmienUlepszenie(int priceup);
    void ulepsz();
    virtual void effect() {}
    void use(mastermind &game, bohater &hero, moc *power, rozgrywka &play);
    friend std::ostream& operator<<(std::ostream& os, const moc& m);
    ~moc();
};

class wiecejProb : public moc
{

public:
    wiecejProb() : moc("Wiecej Prob","Pozwala ci zwiekszyc liczbe prob",12,10,50,100,30,4) {}
    virtual void effect(mastermind &game, int poziom);
};

class odkryjCyfre : public moc
{
public:
    odkryjCyfre() : moc("Odkryj Cyfre","Pozwala odkryc wybrana cyfre",20,5,150,50,50,5) {}
    virtual void effect(mastermind &game, int poziom);
};

class ucieczka : public moc
{
public:
    ucieczka() :moc("Ucieczka","Pozwala ci opuscic rozgrywke bez przykrych konsekwencji",25,5,0,25,0,-5) {}
    virtual void effect(rozgrywka &play);
};

class hpToMp : public moc {
public:
    hpToMp() : moc("Duchowienstwo","Pozwala zamienic zdrowie na mane",0,1,500,0,0,0) {}
    virtual void effect(bohater &hero);
};

class mpToHp : public moc {
public:
    mpToHp() : moc("Wypalenie", "Pozwala zmienic mane na zdrowie",1,1,500,0,0,0) {}
    virtual void effect(bohater &hero);
};

class imortality : public moc{
public:
    imortality() : moc("Niesmertelnosc", "Nie tracisz zdrowia przez okreslony czas",50,3,400,150,150,10) {}
    virtual void effect(rozgrywka &play, int poziom);
};

class moreexp : public moc{
public:
    moreexp() : moc("Mistyczna wiedza", "Zyskuesz wiecej doswiadczenia po zagadce", 40,1,500,0,0,0) {}
    virtual void effect(rozgrywka &play, int poziom);
};

class iLikeMoney : public moc{
public:
    iLikeMoney() : moc("I Like Money", "Zyszkuesz wiecej orbow po zagadce", 40,1,500,0,0,0) {}
    virtual void effect(rozgrywka &play, int poziom);
};

class leczenie : public moc{
public:
    leczenie() : moc("Leczenie", "Uzdrawia twoje rany", 10,8,50,20,30,2) {}
    virtual void effect(bohater &hero, int poziom);
};

#endif // MOC_H

 
//moc.c
#include "moc.h"

moc::moc(string name, string description, int magic, int maxlevel, int cost, int upgrade, int upcost, int manacost){
    nazwa=name;
    opis=description;
    poziom=1;
    maxpoziom=maxlevel;
    cena=cost;
    ulepszenie=upgrade;
    kosztulepszenia=upcost;
    wzrostmany=manacost;
    mana = new int[maxpoziom];
    for(int a=0; a<maxpoziom; a++){
        mana[a]=magic+wzrostmany*a;
    }
}
moc::~moc(){
    delete [] mana;
}

string moc::getNazwa(){
    return nazwa;
}

string moc::getOpis(){
    return opis;
}

int moc::getMana(int a){
    return mana[a];
}

int moc::getPoziom(){
    return poziom;
}

int moc::getMaxPoziom(){
    return maxpoziom;
}
int moc::getCena(){
    return cena;
}

int moc::getUlepszenie(){
    return ulepszenie;
}

void moc::zmienNazwa(string name){
    nazwa=name;
}

void moc::zmienOpis(string description){
    opis=description;
}

void moc::zmienPoziom(int level){
    poziom=level;
}


void moc::zmienCena(int price){
    cena=price;
}

void moc::zmienUlepszenie(int priceup){
    ulepszenie=priceup;
}

void moc::ulepsz(){
    if(poziom!=maxpoziom){
        poziom++;
        ulepszenie+=kosztulepszenia;
    }
    else{
        std::cout << "Moc ma juz maksymalny poziom\n";
    }
}

void moc::use(mastermind &game, bohater &hero, moc *power, rozgrywka &play){
    cout << "Ktory poziom mocy chcesz uzyc?\n";
    int poziom;
    cin >> poziom;
    if(poziom>power->getPoziom() || poziom<=0){
        cout << "Nie masz mocy takiego poziomu\n";
    }
    else{
        cout << power->getMana(poziom-1) << endl;


        if(hero.getMana() < power->getMana(poziom-1)){
            cout << "Masz za malo many\n";
        }
        else{
        //    effect(game,poziom,play,hero);     problem
            hero.zmienMana(-power->getMana(poziom-1));
        }
    }
}



void wiecejProb::effect(mastermind &game, int poziom){
    game.zmienMaxprob(poziom);
    cout << "\nZwiekszyles liczbe prob o: " << poziom << " Masz " << game.getMaxproby() << " prob\n";
}

void odkryjCyfre::effect(mastermind &game, int poziom){

    for(int a = 0; a<poziom; a++){
        cout << "Podaj liczbe ktora chcesz odkryc?\n";
        int num;
        cin >> num;
        cout << "Twoja liczba to: " << game[num-1] << endl;
    }

}

void hpToMp::effect(bohater &hero){

    cout << "Ile zdrowia chcesz zamienic na mane?";
    int num;
    cin >> num;
    if(num > hero.getZdrowie()){
        cout << "Nie posiadasz tyle zdrowia";
    }
    else{
        hero.zmienZdrowie(-num);
        hero.zmienMana(num);
    }
}

void mpToHp::effect(bohater &hero){
    cout << "Ile many chcesz zamienic na zdrowie?";
    int num;
    cin >> num;
    if(num > hero.getMana()){
        cout << "Nie posiadasz tyle many";
    }
    else{
        hero.zmienZdrowie(num);
        hero.zmienMana(-num);
    }
}

void leczenie::effect(bohater &hero, int poziom){

}


void ucieczka::effect(rozgrywka &play){
    play.zmienEscape();
}

void imortality::effect(rozgrywka &play, int poziom){
    play.godmode();

}


void moreexp::effect(rozgrywka &play, int poziom){
    play.zmienExp(poziom);
}

void iLikeMoney::effect(rozgrywka &play, int poziom){
    play.zmienMoney(poziom);
}



std::ostream& operator<<(std::ostream& os, const moc& m){
    os << m.nazwa << " " << m.opis << " " << m.mana[m.poziom] << " " << m.poziom << " " << m.maxpoziom << " " << m.cena << " " << m.ulepszenie << endl;
    return os;
}

Rzeczywiście trochę przekombinowałem niepotrzebnie tworzyłem tyle funkcji wirtualnych w klasie bazowej, dzięki już trochę to poprawiłem, teraz jest jedna klasa przesłaniana przez odpowiednie effekty, ale zostaje mi nadal główny problem właśnie z funkcją effect w use bowiem potrzebne parametry zależały by od tego jaki effect jest akurat wykorzystywany, da się z tym coś zrobić?

1

Źle. Nie rozumiesz na czym polega polimorfizm. Żeby mechanizm funkcji wirtualnych zadziałał, metody muszą być wirtualne, mięc te same nazwy i te same argumenty.
Podam Ci prosty i bardzo głupi przykład (są lepsze sposoby na rozwiązanie takiej sytuacji, tym niemniej to powinno Ci wystarczyć).

 
class Foo {
protected:
	virtual void Fun(const std::string& s, const size_t count) const { std::cout << "Foo" << std::endl; };
public:
	Foo() {};
	virtual ~Foo() {};
	virtual void HaveFun(const std::string& s, const size_t count) const { Fun(s, count); }

};

class Buzz : public Foo {
public:
	Buzz() : Foo() {};
	virtual ~Buzz() {};
protected:
	virtual void Fun(const std::string& s, const size_t count) const { std::cout << s << std::endl; }
};

class Zee : public Foo {
public:
	Zee() : Foo() {}
	virtual ~Zee() {};
protected:
	virtual void Fun(const std::string& s, const size_t count) const { for(size_t i = 0; i < count; i++) std::cout << s << std::endl; }
};

int main()
{
	Foo* buzz = new Buzz();
	Foo* zee = new Zee();
	// Nie ważne jaką wartość podam jako drugi argument i tak na stdout pojawi się tylko raz "asd"
	buzz->HaveFun("asd", 1);
	std::cout << "\n";
	// Teraz "asd" zostanie wypisane na stdout 5-krotnie
	zee->HaveFun("asd", 5);

	delete buzz;
	delete zee;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1