c++ override function of base class - c++

I'm pretty new to object oriented programming in C++, and I can't find a solution to the following problem, I hope this is even possible.
I've got 3 classes: Base and Child, Child2.
All of them got the function talk();.
I want to store Base, Child and Child2 objects in an array, and iterate through them and execute their talk() functions.
This is what I want them to print:
- Base: "base"
- Child: "child"
- Child2: "child2"
Here are my classes:
class Base {
public:
virtual void talk() {
printf("base\n");
}
}
class Child : public Base {
public:
using Base:draw;
void talk() {
printf("child\n");
}
}
class Child2 : public Base {
public:
using Base:draw;
void talk() {
printf("child2\n");
}
}
here is my array:
Base objects[3];
objects[0] = Base();
objects[1] = Child();
objects[2] = Child2();
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}
And the output should be:
base
child
child2

Your code is slicing the objects. When you assign a variable of the base class to the value of derived class, you end up with a base object. At this point, nothing is left of the original derived class, all you have is a base class.
In C++ the way to treat objects polymorphically - that is, to retain the information of original type - is to use either a reference or a pointer. However, you can not put references into arrays.
Which means, you need an array of pointers - but not raw pointers. You want so-called smart pointers. Putting it all together, this is how your code should look like:
std::unique_ptr<Base> objects[3] = {new Base(), new Child(), new Child2()};
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}

Perhaps something like this?
#include <iostream>
#include <cstdio>
class Base
{
public:
virtual void talk()
{
printf("base\n");
}
};
class Child : public Base
{
public:
void talk()
{
printf("child\n");
}
};
class Child2 : public Base
{
public:
void talk()
{
printf("child2\n");
}
};
int main()
{
Base** objects;
objects = new Base * [3];
objects[0] = new Base();
objects[1] = new Child();
objects[2] = new Child2();
for(int i = 0; i < 3; i++)
objects[i]->talk();
}
Output is:
base
child
child2

So something like:
#include <stdio.h>
class Base {
public:
virtual void talk() {
printf("base\n");
}
};
class Child : public Base {
public:
void talk()
{
printf("child\n");
}
};
class Child2 : public Base {
public:
void talk()
{
printf("child2\n");
}
};
int main()
{
Base* objects[3];
objects[0] = new Base();
objects[1] = new Child();
objects[2] = new Child2();
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}
}

Related

Architecture of sub-classes in C++

I learn C++ OOP-paradigm and want to ask related question:
Assumption
We have a base class:
class Base {
public:
virtual SomeType PowerMethod() { return SomeType{} };
}
We have a variable target and subclass which realizes some calculations with target variable based on the constructor's parameter (simple calculations or complicated calcs):
class Calc : public Base {
public: // using only public access to simplify real code structure
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
Question
How to optimally realize two classes which based on different methods (Simple or Complex) but provide the same functionality of PowerMethod()?
My solution
class SimpleCalc : public Calc {
bool isSimple = true;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
class ComplexCalc : public Calc {
bool isSimple = false;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
This solution is pretty "ugly" and I want to ask you how to make it more readable.
Thank you!
I think that in your code, you didn't mean to craete a new Calc object, but instead call it on the superclass. This can be done like so:
Calc::Simple();
You can override the method PowerMethod, but still call the superclass's code:
virtual SomeType PowerMethod() override {
//do something
Base::PowerMethod();
}
If your problem is more complicated, and polymorphism and superclasses can't help you, you can always declare some method protected, so that only subclasses can access it. So, you could for example do this:
class Calc : public Base {
protected:
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
public:
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
class SimpleCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Simple();
return Calc::target;
};
};
class ComplexCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Complex();
return Calc::target;
};
};
If your target is to learn OOP then you can use a factory design pattern to create your final calculator based on isSimple condition:
#include <iostream>
class Base
{
public:
Base()
{
target = 0;
}
int target;
virtual void PowerMethod() = 0;
};
class SimpleCalc : public Base
{
virtual void PowerMethod() { target = 0; }
};
class ComplexCalc : public Base
{
virtual void PowerMethod() { target = 1000; }
};
class CalcFactory
{
public:
virtual Base* createCalc(bool isSimple)
{
if (isSimple)
return new SimpleCalc();
else
return new ComplexCalc();
}
};
int main()
{
CalcFactory factory;
Base * base1 = factory.createCalc(true);
Base * base2 = factory.createCalc(false);
base1->PowerMethod();
base2->PowerMethod();
std::cout << base1->target << std::endl;
std::cout << base2->target << std::endl;
}

Memory issue in casting from a Derived class to a Base class

I have a class Base and another class Derived (derived from Base).
Also I have a 2 functions GetValue(Base*) and GetDerivedValue(Derived*).
Now, from the main() function, I have access to only GetValue(), but I need the value of both Base and Derived classes.
class Base
{
public:
Base ()
{
abc =0;
}
~Base ()
{
abc =0;
}
int abc;
};
class Derived : public Base
{
public:
Derived ()
{
def =0;
}
~Derived ()
{
def =0 ;
}
int def;
};
int GetDerivedValue (int &def)
{
def = 5;
}
int GetValue (Base *&pbase)
{
Derived *d = new Derived ();
GetDerivedValue (d->def);
pbase = (Base *) d;
}
int main ()
{
Base *pbase = NULL;
GetValue (pbase);
// Goal here is to get the avlue of def as 5 without any memory issue
}
Where should I release the pointers to make sure there is no memory errors?
I think you are looking for something like this:
class Base
{
public:
Base() : abc(0) {}
virtual ~Base() {}
int abc;
};
class Derived : public Base
{
public:
Derived() : def(0) {}
~Derived() {}
int def;
};
void GetDerivedValue(int &def)
{
def = 5;
}
void GetValue(Base* &pbase)
{
Derived *d = new Derived;
GetDerivedValue(d->def);
pbase = d;
}
int main()
{
Base *pbase = NULL;
GetValue(pbase);
// use pbase as needed...
delete pbase;
}
Which would be better written using std::unique_ptr instead:
#include <memory>
class Base
{
public:
virtual ~Base() = default;
int abc = 0;
};
class Derived : public Base
{
public:
int def = 0;
};
void GetDerivedValue(int &def)
{
def = 5;
}
std::unique_ptr<Base> GetValue()
{
auto d = std::make_unique<Derived>();
GetDerivedValue(d->def);
return d;
}
int main()
{
auto pbase = GetValue();
// use pbase as needed...
}

I created deque<CObject*> and added different type of element. How can I change attribute of this elements?

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();
}

C++ polymorphism. Methods

I have a small problem which I can't handle.
Currently I'm working over a project about a marathon between animals.
I'm obliged to use polymorphism even though it could be easier without.
Here's a sample of my code:
class Animal
{
public:
virtual void run()=0;
virtual bool return_if_finished()=0;
virtual float return_distance()=0;
}
class Turtle :public Animal
{
int id;
float distance; //etc.
public:
void run();
bool return_if_finished();
float return_distance();
void set_id(int i);
void a_friend();
}
class Snail :public Animal
{
float distance; //etc.
public:
void run();
bool return_if_finished();
float return_distance();
void broken_leg();
}
So that's a sample. All classes that inherit from the main class "Animal" have only three mutual methods. They also have some that only they do need.
If I want to write a code in a method where they "run" like that:
...
Animal* turtles = new Turtle[amount];
Animal* snails = new Snail[amount];
for(int i=0; i<amount; i++)
turtles[i].set_id(i);
I can't compile it because "class Animal has no member called "set_id"".
I could create all these methods for each class but that would be totally pointless. I bet there's a quick solution to that.
If I create a virtual void "set_id(int)" for the class "Animal" then I get the error message that not all classes that inherit from animal contain that method.
So any help would be very appreciated. Thank you
If I create a virtual void "set_id(int)" for the class "Animal" then I get the error message that not all classes that inherit from animal contain that method.
I suspect you defined Animal::set_id as a pure virtual, like this:
virtual void set_id(int) = 0;
What you really want is to define it in the Animal class as a virtual method, like this:
virtual void set_id(int _id) {id = _id};
Also, the id member variable needs to be moved to the Animal class instead of Turtle
EDIT:
Expanding the answer to include the full code:
class Animal
{
public:
Animal() : id(-1) {}
virtual ~Animal() {}
virtual void run() = 0;
virtual bool return_if_finished() = 0;
virtual float return_distance() = 0;
void set_id(int i) { id = i; }
private:
int id;
};
class Turtle :public Animal
{
public:
void run() {};
bool return_if_finished() { return true; };
float return_distance() { return 2.0; };
void a_friend() {};
};
class Snail :public Animal
{
public:
void run() {};
bool return_if_finished() { return false; };
float return_distance() { return 1.0; };
void broken_leg() {};
};
int main()
{
const int amount = 10;
Turtle turtles[amount];
Snail snails[amount];
for (int i = 0; i < amount; i++) {
turtles[i].set_id(i);
}
}
First of all, using:
Animal* turtles = new Turtle[amount];
Animal* snails = new Snail[amount];
is a bad idea.
The pointer arithmetic on turtles and snails will be based size of Animal. If you use tutles[i] for all i not equal to 0, you'll run into undefined behavior. There is probably an SO question somewhere about that.
Use a vector of pointers instead. It will be also easier to initialize them.
std::vector<Animal*> turtles(amount); = new Turtle[amount];
for(int i=0; i<amount; i++)
{
Turtle* tptr = new Turtle;
tptr->set_id(i);
turtles[i] = tptr;
}
Better yet, use a smart pointer.
std::vector<std::shared_ptr<Animal>> turtles(amount); = new Turtle[amount];
for(int i=0; i<amount; i++)
{
Turtle* tptr = new Turtle;
tptr->set_id(i);
turtles[i] = std::shared_ptr<Animal>(tptr);
// Or
// turtles[i].reset(tptr);
}

Instantiating Derived objects from the Base class

Trying to create a Driver type class where, below, Base is the Driver that is passed a type at instantiation. The type, the 2 in this case, is used to construct the correct derived object.
My compiler is throwing a Declaration syntax error on the "Class Base" line.
My end goal is to be able to do this:
Base *B;
B = new Base(2);
if(B)
{
B->DoStuff();
B->DoMoreStuff();
delete B;
}
Here is my code that won't compile...
class Base
{
public:
Base(int h);
virtual ~Base();
private:
int hType;
Base *hHandle;
};
class Derived1 : public Base
{
public:
Derived1();
virtual ~Derived1();
};
class Derived2 : public Base
{
public:
Derived2();
virtual ~Derived2();
};
Base::Base(int h)
{
hType = h;
switch(h)
{
case 1:
hHandle = new Derived1;
break;
case 2:
hHandle = new Derived2;
break;
}
}
Derived1::Derived1():Base(1)
{
printf("\nDerived1 Initialized\n\n");
}
Derived2::Derived2():Base(2)
{
printf("\nDerived2 Initialized\n\n");
}
Below is updated code to show the full source. I think I now understand why it will not compile. As is pointed out below, I have an endless loop of calls to 'new'
#include <stdio.h>
class Base
{
public:
Base();
Base(int h);
Create (int h);
virtual ~Base();
private:
int hType;
Base *hHandle;
};
class Derived1 : public Base
{
public:
Derived1();
virtual ~Derived1();
};
class Derived2 : public Base
{
public:
Derived2();
virtual ~Derived2();
};
Base::Base()
{
}
Base::Base(int h)
{
Create(h);
}
Base::Create(int h)
{
hType = h;
switch(h)
{
case 1:
hHandle = new Derived1;
break;
case 2:
hHandle = new Derived2;
break;
}
}
Derived1::Derived1()
{
printf("\nDerived1 Initialized\n\n");
}
Derived2::Derived2()
{
printf("\nDerived2 Initialized\n\n");
}
It looks like you're trying to do a class factory.
I'd recommend that you have a static method in Base that returns either Derived1 or Derived2.
class Base
{
public:
static Base* Create(int);
virtual void DoStuff() = 0;
}
class Derived1 : public Base
{
Derived1()
{
printf("\nDerived1 Initialized\n\n");
}
virtual void DoStuff()
{
}
}
class Derived2 : public Base
{
Derived2()
{
printf("\nDerived2 Initialized\n\n");
}
virtual void DoStuff()
{
}
}
Base* Base::Create(int n)
{
if (n==1)
return new Derived1();
else if (n==2)
return new Derived2();
else
return nullptr;
}
void main()
{
Base* B = Base::Create(2);
if(B)
{
B->DoStuff();
delete B;
}
}