Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] jeden obiekt, wybór miedzy 6 klasami

Ostatnio zmodyfikowano 2021-12-26 23:59
Autor Wiadomość
Dabba
Temat założony przez niniejszego użytkownika
[C++] jeden obiekt, wybór miedzy 6 klasami
» 2021-12-26 19:44:39
Cześć, nie jestem amatorem, ale też nie czuję się bardzo swobodnie z programowaniem obiektowym w C++. Robię projekt na zaliczenie przedmiotu na studia - prosta gra RPG. Stworzyłem kilka klas (Fire [mage], Frost [mage], Archer, Assassin, Bruiser, Werewolf) i pojawił się problem. Chce zadeklarować obiekt 'player' w zależności od wyboru użytkownika czyli:
Jeżeli użytkownik wybiera, że chce grać Fire Magiem tworzy się obiekt Fire player.
Jeżeli użytkownik wybiera, że chce grać Archerem tworzy się obiekt Archer player.

I tu zwracam się z pytaniem, czy coś takiego jest w ogóle możliwe? Probowałem wskaźników, probowałem switcha i ifa (ale tu niestety wiem, że te obiekty tworzą się lokalnie i nie działają globalnie) i teraz już nie wiem w jaki sposób mogę to rozwiązać.
Zależy mi na rozwiązaniu problemu w mainie, a jeśli się nie da to będę chyba musiał pogrzebać w klasach.

Z góry dziękuję za pomoc!


Plik main.cpp
C/C++
...

Fire player;
Frost player_tmp1;
Archer player_tmp2; //probowalem przyrownywac w ifach/switchu nazwy obiektów do siebie, ale nie do końca wiedziałem w jaki sposób
Assassin player_tmp3;
Bruiser player_tmp4;
Werewolf player_tmp5;

int cValue = createCharacter(); //createCharacter() zwraca mi dana cyfre dla danej specjalizacji
switch( cValue ) {
case 1: //Fire
    //?
   
break;
case 2: //Frost
    //?
   
break;
case 3: //Archer
    //?
   
break;
case 4: //Assassin
    //?
   
break;
case 5: //Bruiser
    //?
   
break;
case 6: //Werewolf
    //?
   
break;
}

...
P-179143
DejaVu
» 2021-12-26 19:53:07
Odpowiedź brzmi: dziedziczenie i dynamiczna alokacja pamięci. Przykład:
C/C++
class Player {
public:
   
virtual ~Player();
};

class PlayerArcher
    : public Player
{
   
// tu implementacja
};

class PlayerBruiser
    : public Brusier
{
   
// tu implementacja
};

int main()
{
   
Player * player = nullptr;
   
///...
   
switch( selectedCharacter )
   
{
   
case 1: player = new PlayerArcher(); break;
   
case 2: player = new PlayerBruiser(); break;
       
//...
   
}
   
return 0;
}
Potem powinieneś poczytać jeszcze o metodach wirtualnych, aby móc łatwo wykonywać akcje gracza z poziomu obiektu typu Player*.
P-179144
Dabba
Temat założony przez niniejszego użytkownika
» 2021-12-26 20:25:12
Zrobiłem (chyba) wszystko tak jak na przykładzie i teraz pokazują mi się takie błędy. Co zrobiłem nie tak?


Undefined symbols for architecture x86_64:
  "Player::~Player()", referenced from:
      Entity::~Entity() in Fire.cpp.o
      Entity::~Entity() in Frost.cpp.o
      Entity::~Entity() in Archer.cpp.o
      Entity::~Entity() in Assassin.cpp.o
      Entity::~Entity() in Bruiser.cpp.o
      Entity::~Entity() in Werewolf.cpp.o
  "typeinfo for Player", referenced from:
      typeinfo for Entity in Fire.cpp.o
      typeinfo for Entity in Frost.cpp.o
      typeinfo for Entity in Archer.cpp.o
      typeinfo for Entity in Assassin.cpp.o
      typeinfo for Entity in Bruiser.cpp.o
      typeinfo for Entity in Werewolf.cpp.o
  "vtable for Player", referenced from:
      Player::Player() in Fire.cpp.o
      Player::Player() in Frost.cpp.o
      Player::Player() in Archer.cpp.o
      Player::Player() in Assassin.cpp.o
      Player::Player() in Bruiser.cpp.o
      Player::Player() in Werewolf.cpp.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [TheGame] Error 1
make[2]: *** [CMakeFiles/TheGame.dir/all] Error 2
make[1]: *** [CMakeFiles/TheGame.dir/rule] Error 2
make: *** [TheGame] Error 2

Dziedziczenie klas u mnie w projekcie wyglada następująco:

Fire:Hero:Entity:Player
Frost:Hero:Entity:Player
itd...
P-179145
DejaVu
» 2021-12-26 20:29:22
Nie zaimplementowałeś destruktora Player::~Player(){}
P-179146
Dabba
Temat założony przez niniejszego użytkownika
» 2021-12-26 20:44:11
Okej, dziękuję bardzo, wydaje mi się, że wszystko już jest w porządku na tym etapie, tylko teraz mam problem związany z tym, jak to sprawdzić. Próbuję wywołać w cout'cie imię podane przez użytkownika.


Klasa Hero.h (z której dziedziczy potem każda kolejna klasa - Fire, Frost etc)
C/C++
class Hero
    : public Entity
{
protected:
   
double armor = 50;
   
double crit = 4;
   
double money = 10;
   
double xp = 0;
   
double resource = 100;
   
public:
   
string name;
   
string spec;
   
main.cpp (z linijką kodu który próbuję wykonać)
C/C++
cout << player.name << " budzi sie w ciemnym miejscu." << endl;


wpisanie player/Player/Hero/Entity/ nie daje rezultatów, a być może w dalszym przebiegu gry będę potrzebował zwracać się do poszczególnych zmiennych w klasie.
P-179147
DejaVu
» 2021-12-26 23:46:24
Poczytaj o metodach wirtualnych i jak je zrozumiesz to pokombinuj trochę z nimi. W programowaniu ten sam cel można osiągnąć na wiele sposobów, więc poznaj najpierw rekomendowane narzędzie, a potem zacznij zadawać kolejne pytania.
P-179148
pekfos
» 2021-12-26 23:59:52
nie daje rezultatów
Co to może znaczyć? Nie wiadomo jak wygląda kod i jak wygląda błąd kompilacji. player jest wskaźnikiem w tym kodzie? Odwołanie do składowej poprzez wskaźnik się robi przez ->.
C/C++
player->name
// albo
( * player ).name
P-179149
« 1 »
  Strona 1 z 1