I'm still fairly new to C++ and inheritance has gotten me in a pickle.
I know this works in C# since I'm always using Base.();
I'm hoping to be able to call a vector array of PlayerCharacter, derived from Entity.
Currently when I call it, it only calls Entity's update method.
int main()
{
vector<Entity*> list;
list.push_back(&PlayerCharacter());
for(int i = 0; i < list.size(); i++)
{
list[0]->Update();
}
}
class Entity
{
public:
Entity(void);
~Entity(void);
int hitpoints;
virtual void Update(void);
};
void Entity::Update(void)
{
int a = 0;
a++;
}
class PlayerCharacter : public Entity
{
public:
PlayerCharacter(void);
~PlayerCharacter(void);
bool Move();
void Update() override;
};
void PlayerCharacter::Update(void)
{
int a = 0;
a--;
}
list.push_back(&PlayerCharacter()); i think this is undefined behavior in your code.
In your case you should allocate the data on the heap like this: list.push_back( new PlayerCharacter() ); otherwise if you do this &PlayerCharacter() then the PlayerCharacter variable will be destroyed immediately and the pointer inside the list will point to garbage bytes.
Also to track which function is called you can use the debugger or print something in the console from each Update function.
This Works :
Few changes though : 1) You dont need to put Override 2) Definition of Constructor and destructor once declared 3) Created object of derived class and passed it to the list.
Output is : Inside PlayerCharacter
If you want to call base class update method method remove the volatile keyword. Or use base class pointer pointing to base class object.
class Entity
{
public:
Entity();
~Entity();
int hitpoints;
virtual void Update(void);
};
Entity::Entity()
{
}
Entity::~Entity()
{
}
void Entity::Update(void)
{
std::cout << " Inside Entity" <<std::endl;
int a = 0;
a++;
}
class PlayerCharacter : public Entity
{
public:
PlayerCharacter();
~PlayerCharacter();
bool Move();
void Update();
};
void PlayerCharacter::Update(void)
{
std::cout << " Inside PlayerCharacter" <<std::endl;
int a = 0;
a--;
}
PlayerCharacter::PlayerCharacter()
{
}
PlayerCharacter::~PlayerCharacter()
{
}
int main()
{
vector<Entity*> list;
PlayerCharacter ObjPlayerCharacter;
list.push_back(&ObjPlayerCharacter );
for(unsigned int i = 0; i < list.size(); i++)
{
list[0]->Update();
}
}
Related
I created:
class CMap:{
public
std::deque<CObject*> obiekty;
}
class CBullet{
public:
int damage;
}
and I added different type of element ( e.g. CTank, CBullet...)
and I want change atributes using deque
for( size_t i=0; i<game->Mapa->obiekty.size(); i++){
if(typeid(*(game->Mapa->obiekty[i]))==typeid(CBullet)){
this->HP=this->HP - game->Mapa->obiekty[i] (?? my problem/I can't do it ?? ->damage);
}
}
At first you need to inherit your derivate classes(CBullet, CTank) from base class (CObject), like this
//Base clase
class CObject
{
public:
//...
virtual ~CObject(){}; // Don't forget about virtual desctructor
};
class CBullet: public CObject
{
public:
//...
~CBullet(){};
void DoBulletMethod(){};
};
class CTank: public CObject
{
public:
//...
~CTank(){};
void DoTankMethod(){};
};
Then you can check all objects by dynamic_cast, like this:
for( size_t i=0; i< game->Mapa->obiekty.size(); i++)
{
if(dynamic_cast<CBullet*>(game->Mapa->obiekty[i]) != nullptr)
{
CBullet * BulletObj = dynamic_cast<CBullet*>(game->Mapa->obiekty[i]);
BulletObj->DoBulletMethod();
}
else if(dynamic_cast<CTank*>(game->Mapa->obiekty[i]) != nullptr)
{
CTank * TankObj = dynamic_cast<CTank*>(game->Mapa->obiekty[i]);
TankObj->DoTankMethod();
}
}
Or you can use polymorphism and create virtual methods, without further detection of current object type, for example create one virtual method in base class and override it in derivate classes:
//Base clase
class CObject
{
public:
//...
virtual ~CObject(){}; // Don't forget about virtual desctructor
virtual void DoActionInLoop()
{
//No action in base class
}
};
class CBullet: public CObject
{
public:
//...
~CBullet(){};
virtual void DoActionInLoop() override
{
std::cout << "I am bullet I can do here my tasks" << std::endl;
}
};
class CTank: public CObject
{
public:
//...
~CTank(){};
virtual void DoActionInLoop() override
{
std::cout << "I am tank and I can do here my tasks" << std::endl;
}
};
Then just call this method on each CObject* instance and get your polymorphism:
for( size_t i=0; i< game->Mapa->obiekty.size(); i++)
{
game->Mapa->obiekty[i]->DoActionInLoop();
}
Say I have these two classes:
class Object {
public:
virtual void update();
};
class Actor : public Object {
public:
void update();
}
Also assume that I am creating instances of the actor class as follows:
class somethingElse {
public:
void init();
std::vector<Object*> objects;
}
void somethingElse::init()
{
Actor tmp;
Object * tmpo = &tmp;
objects.push_back(tmpo);
}
I later iterate through objects:
for (int i = 0; i < objects.size(); i++)
objects.at(i)->update();
Placing a breakpoint at the two versions of update() revealed that the one being called is the one from the object class, and not the one from the actor class. Why is this, and is there any way around this problem?
In somethingElse::init() Actor tmp will go out of scope and be destroyed. The pointer will point to an object that no longer exists.
new could help here, but it would be safer to use a smart pointer, such as std::shared_ptr for example:
#include <iostream>
#include <vector>
#include <memory>
class Object {
public:
virtual void update() { std::cout << "Object update()\n"; }
virtual ~Object() = default;
};
class Actor : public Object {
public:
void update() { std::cout << "Actor update()\n"; }
};
class somethingElse {
public:
void init();
std::vector<std::shared_ptr<Object>> objects;
};
void somethingElse::init()
{
//Actor tmp;
auto tmpo = std::make_shared<Actor>();
//Object * tmpo = &tmp;
objects.push_back(tmpo);
}
int main()
{
somethingElse objs;
objs.init();
auto& objects = objs.objects;
for(int i = 0; i < objects.size(); i++)
objects.at(i)->update();
}
I am trying to wrap my head around using a manager object to loop through the objects in an array and invoke the virtual functions for each object. Here is my code so far, thanks to some very helpful suggestions, it compiles but still doesn't make use of polymorphism the way that I want it to. Thanks in advance for any tips that can point me in the right direction.
#include <iostream>
class avian{
private:
static const int max_birds = 25;
avian* birds[max_birds];
int num_birds;
public:
avian() : num_birds(0){}
virtual ~avian() {
for (int i = 0; i < num_birds; ++i) { delete birds[i]; }
}
bool add(avian* b){
if (num_birds >= max_birds){ return false; }
birds[num_birds++] = b;
return true;
}
void make_bird(){
for (int i = 0; i< num_birds; ++i){birds[i]->make_bird();
}
}
virtual void lay_eggs(){} ;
virtual void bird_noise(){} ;
};
class turkey : public avian{
public:
void lay_eggs() const{ std::cout << "000\n"; }
void bird_noise() const { std::cout << "Gobble Gobble Gobble!\n"; }
};
class chicken : public avian {
public:
void lay_eggs() const { std::cout << "OOOOO\n"; }
void bird_noise() const { std::cout << "Bock Bock Bock!\n"; }
};
class quail : public avian{
public:
void lay_eggs() const { std::cout << "ooooooooo\n"; }
void bird_noise() const { std::cout << "Chirr Chirr Chirr!\n"; }
};
int main(){
avian* my_turkey = new turkey;
my_turkey->make_bird();
my_turkey->lay_eggs();
my_turkey->bird_noise();
delete my_turkey;
return 0;
}
You don't have a virtual base class destructor:
virtual ~avian() { ... }
Calls to delete pointer_to_avian will will call avian::~avian, but they will not propagate to the destructors of derived classes - UB, as compiler says.
avian::lay_eggs is declared, but not defined. Did you mean to make it pure virtual function? You've overriden it in every derived class.
avian::bird_noise - same as above
You forgot to delete my_turkey in main - you're leaking memory.
Your base virtual methods are not marked as const. But methods in derived classes are const. So they are not overriden.
Rule of thumb is to use override keyword in order to avoid such errors
I'm trying to accomplish something but am unsure if it's even possible.
The quick idea is, I'm writing a game and want to have a single array (or vector) of different monsters. Every class that inherits the main class Monster simply overrides its functions (but doesn't add any new ones).
Then, when I go through the list of monsters, I can just call the same functions that all of them have.
Here's some code to show what I'm trying to accomplish:
class Monster
{
public:
int hp; //hit points
int atp; //attack power
int def; //defense
bool attacking;
bool defending;
virtual void attack();
virtual void defend();
};
void Monster::attack()
{}
void Monster::defend()
{}
class Goblin: public Monster
{
public:
virtual void attack() override;
virtual void defend() override;
};
void Goblin::attack()
{
//Goblin's attacking patterns
}
void Goblin::defend()
{
//Goblin's defending patterns
}
class Orc: public Monster
{
public:
virtual void attack() override;
virtual void defend() override;
};
void Orc::attack()
{
//Orc's attacking patterns
}
void Orc::defend()
{
//Orc's defending patterns
}
int main(void)
{
//This is where I'm not sure what to do:
//Initialize monsters. Make some Goblins, some Orcs
int num_monsters = 10;
Monster* monster_list;
monster_list = new Monster[num_monsters];
for (int i = 0; i < num_monsters; i++)
{
int which = rand() % 2;
switch (which)
{
case 0: //Goblin
monster_list[i] = new Goblin;
break;
case 1: //Orc
monster_list[i] = new Orc;
break;
}
}
bool quit = false;
while (quit == false)
{
for (int i = 0; i < num_monsters; i++)
{
if (monster_list[i].attacking == true)
monster_list[i].attack();
if (monster_list[i].defending == true)
monster_list[i].defend();
}
}
}
Hopefully that illustrates what I'm trying to do.
I know this doesn't work, but I'm not sure how to make it work.
Thanks for any advice on this!
You'll need to use a vector of pointers to a base class.
std::vector<Monster*> monsters;
monsters.push_back(new FireDragon());
monsters.push_back(new IceDragon());
Then you'll be able to iterate through the monsters vector and call a common method.
for(auto monster = monsters.begin(); monster != monsters.end(); monster++)
{
(*monster)->attack();
}
The classes:
class Monster {
public:
virtual ~Monster() {}
virtual void attack() = 0;
};
class FireDragon : public Monster {
public:
~FireDragon();
void attack()
{
std::cout << "Fire breath!" << std::endl;
}
};
class IceDragon : public Monster {
public:
~IceDragon();
void attack()
{
std::cout << "Ice breath!" << std::endl;
}
};
As a side note be sure to create virtual destructors in the derived classes or else the base class' destructor will be called.
ETA: Here is the implementation with smart pointers:
/*
Use std::unique_ptr<Monster> if your implementation doesn't need to pass the
monster objects around
*/
std::vector<std::shared_ptr<Monster>> monsters;
/*
Use std::make_unique<FireDragon>() if using unique_ptr
*/
monsters.push_back(std::make_shared<FireDragon>());
monsters.push_back(std::make_shared<IceDragon>());
for(auto monster : monsters)
{
monster->attack();
}
I am trying to do something like this with c++.
void showContensofArray(void *data[])
{
//In this function have to display the values of respective objects.
// Any ideas how do I do it?
}
int main(){
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
void *dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray); //function
}
If you want to treat the objects in the data[] generically (i.e by calling a common function on them to extract a description or values) then define a class hirachy for your objects and in your showContentsofArray function call virtual methods on your (common base class) object pointers.
This is a textbook example of Polymorphism:
"polymorphism allows values of different data types to be handled using a uniform interface."
In the example below the base class BaseObject defines the uniform interface.
class BaseObject {
virtual string description() { return "Base object"; }
virtual bool bounces() { return false; }
}
class B : public BaseObject {
string description() { return "Im a B object" }
bool bounces() { return true; }
}
class A : public BaseObject {
string description() { return "Im an A object" }
}
void showContensofArray(BaseObject* data[], int size) {
for (int i=0; i<size; i++) {
cout << data[i]->description();
if (data[i]->bounces())
cout << "I bounce!";
}
}
int main() {
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
BaseObject* dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray);
}
Will output:
Im an A object
Im a B object
I bounce!
void showContensofArray(void *data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
And every Class should have an implementation of the method print() that knows how to print its values.
You could also use inheritance.
EDIT:
#Ricibob's answer is correct, but if you need to do the casting inside the function, you need to do something like this:
#include <iostream>
using namespace std;
class Base{
public:
virtual void print()=0;
};
class A: public Base{
public:
void print(){
cout<<"Object A"<<endl;
}
};
class B: public Base{
public:
void print(){
cout<<"Object B"<<endl;
}
};
void showContensofArray(void* data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
int main(){
A a;
B b;
void* v[2];
v[0]= &a;
v[1] = &b;
showContensofArray(v,2);
return 0;
}
You can't evade inheritance.
Just cast back to the original type:
A* p1 = static_cast<A*>(data[0]);
B* p2 = static_cast<B*>(data[1]);