polymorphism: calling overrided functions without pointers - c++

I am doing some experimentation with C++.
I've been imporessioned by some behaviours with polymorphism.
In other languages (such as c#), when I assign an object based on a derived class to an object of BaseType: this object starts working with the derived class code. Or If I have a list of BaseType objects and I put derived class based objects in it: every element works according to the specific Type.
In c++ no...
I obtained this behaiviour in C++ just using pointers.
Is there an alternative way? Have i missed something?
Here's my code example:
class GenericCar
{
public:
virtual void PrintModelName()
{
std::cout << "No Model Defined \n";
}
};
class FerrariCar : public GenericCar
{
public:
void virtual PrintModelName() override
{
std::cout<<"Ferrari \n";
}
};
int main()
{
std::cout << "Hello World!\n";
//instance of two Ojects: A generic Car (Base Class) and a Ferrari (inherited class)
GenericCar Car = GenericCar();
FerrariCar Ferrari = FerrariCar();
Car.PrintModelName(); //base method
Ferrari.PrintModelName(); //overrided method
((GenericCar)Ferrari).PrintModelName(); //base method....
//declaring a List of Generic Cars (Base Class)
list<GenericCar> ListOfCars;
ListOfCars.push_back(Car); //adding BaseClass based Object
ListOfCars.push_back(Ferrari); //adding InheritedClass based Object
//for each element i want to print the model name of the Car.
for (GenericCar & CarElement: ListOfCars)
{
//The base method is called for each element. (The second object is Ferrari but the base method is executed)
CarElement.PrintModelName();
}
//Now declaring a List of GenericCar pointers
list<GenericCar*> ListOfCarsPointers;
ListOfCarsPointers.push_back(&Car); //adding BaseClass based object address
ListOfCarsPointers.push_back(&Ferrari);//adding InheritedClass based object address
//for each element i want to print the model name of the Car.
for (GenericCar* & CarElement : ListOfCarsPointers)
{
//The correct method is invoked. For the object "Ferrari" is called the overrided function instead of base class code)
CarElement->PrintModelName();
}
//Now i try to assign Ferrari to Car (inherited to base)
Car = Ferrari;//assignment
Car.PrintModelName();//method invoke. Here, the base method is invoked. Not the overridden code...
char c;
std::cin >> c;
}
In C#, for example, the overridden method is called despite the explicit cast to the base class: (BaseClass)InherithedClassObject.method() invokes the overridden method and not the base one.
In the iteration of the list: the overridden method is ivoked, too (Always C#).
In c++ Have I to use always pointer in order to ensure the possibility of having a polymorphic behavior? As a consequence: Have I to manage always memory allocation destroyng objects explicitally?

When you placed Ferrari in your first list you experienced type erasure - the "GenericCar" structure was copied into the list and anything that could have identified that it was a "FerrariCar" was lost.
You need a pointer or reference to invoke polymorphic functions, have a pointer or reference gives you access to the virtual table for your object.
To have a list that could store store such car objects and be passed around to different functions you will probably want to use smart pointers so that you don't wind up with dangling pointers or memory leaks.
#include <memory>
...
list<shared_ptr<GenericCar>> cars;
cars.push_back(shared_ptr<GenericCar>(new GenericCar()));
cars.push_back(shared_ptr<GenericCar>(new FerrariCar()));
for ( shared_ptr<GenericCar> & car : cars )
car->PrintModelName();

Related

C++ new keyword in inheritance with different types

I recently started learning OOP. Forgive me if this is a noob question. My question is,
I have thought new keyword is used with only same datatypes such as:
char* p = new char; // OR
int* myArr = new int[i] //etc...
While studying inheritance and virtual functions I've come across this:
#include <iostream>
using namespace std;
class Human {
public:
virtual void className() {
cout << "Human" << endl;
}
};
class Asian : public Human {
public:
void className() {
cout << "Asian" << endl;
}
};
int main() {
Human* h1 = new Asian();
h1->className();
}
In the main function, we initialize the pointer with the base class and then there is the derived class after new keyword? What do those 2 datatypes represent, how am I supposed to use them?
Note that in your case, the class Human is accessible class of Asian and
$11.2/5 states -
If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]
According to the above quoted statement, you can convert a pointer to the derived class Asian to a pointer to the base class Human(which means from Asian* to Human*), which is what you did when you wrote:
Human* h1 = new Asian();
In the above statement, on the left hand side we have a pointer named h1 of type Human and on the right hand side by using the keyword new we are creating an object of type Asian on the heap. But note that using new has a second effect which is that after the object of type Asian is created on the heap then a pointer to that object is returned. So essentially,
on the right hand side we get a pointer to Asian (Asian*).
Now as i have already explained(quoted) at the beginning of the answer, you can convert a pointer to Asian to a pointer to Human which is what has happened here.
Now when you wrote:
h1->className();
There are 3 important facts that you have to consider:
className is a virtual function/method
h1 is a pointer
Asian inherit Human publicly
and according to virtual function documentation
a virtual function is a member function you may redefine for other derived classes, and can ensure that the compiler will call the redefined virtual function for an object of the corresponding derived class, even if you call that function with a pointer or reference to a base class of the object.
And so the result is that the derive class' function named className is called at run-time and we see Asian printed on the console.
This is the advantage of using OOP. Suppose you have a car factory and you're making sedan, hatchback and etc. All of them are cars, so they have four wheels, engines, and so on. In order to don't have the same data many times, you can use inheritance. Both the parent and the child class can cast to each other but an example for you to understand is that suppose you have a class that you modify a car. As I didn't specify the type of car, it can be a sedan or a hatchback, instead of having 2 different functions you can have one function that takes the parent object(Car).
virtual keyword specifies that the child version of the function should run instead of the parent. So in your example, since we are making an Asian object, we will call the child(Asian) version of the className. If there was no virtual keyword then the parent version would run.

How to put unknown child classes of a base class in one data structure and call an overridden base class function in C++

I have a "chain" class, meaning a class that manages a sequence of objects with a common base class.
This chain class should execute the member function processSample(a, b) for any child class (of baseClass) I add.
I want to be able to code more child classes (with a processSample(a, b) function) later on, and add them to the chain without having to edit the chain class.
I could use a template in the add function but this doesn't solve the problem that there is no data structure for different datatypes (of different sizes) right?
Functions of the children called in the Chain class should all be overridden virtuals from the base class.
class baseClass
{
public:
virtual float processSample(int a, float b)
{
}
};
class Chain
{
const int maxChilds = 20;
?sometype? allChilds[maxChilds];
public:
float processSample(int c, float d)
{
for (int i = 0; i < maxChilds; i++)
{
input = allChilds[i].processSample(a, b);
}
return input;
}
void addChild(?sometype? newChild)
{
allChilds.push_back(newChild)
}
}
You would want to use pointers or references, to avoid initialization or copy operations as part of creating the class.
For example
class Chain
{
const int maxChilds = 20;
baseClass allChilds[maxChilds];
Will create, and initialize an array of 20 baseClass instances. Whereas this:
class Chain
{
const int maxChilds = 20;
baseClass* allChilds[maxChilds];
Will create an array of pointers to baseClass, which can also point to instances of any child classes. Do consider which class will be responsible for allocation and de-allocation of the memory for these instances (this can either be within this class, or the caller / user of this class - which one is ideal will depend on the rest of your design). You could also consider using a smart pointer instead and let that manage the memory for you: https://en.cppreference.com/book/intro/smart_pointers
Similarly:
void addChild(baseClass newChild)
Will use pass-by-value to pass in a copy of newChild (using the copy constructor of baseClass), any instances of child classes will either fail or be converted to an instance of baseClass. Whereas if you instead go with:
void addChild(baseClass& newChild)
It will use pass-by-reference instead, and the function will receive a reference to the original object.
The nice effect of virtual is, that you "call a function of the base class", but the function of the derived class will be executed.
So ?sometype? allChilds[maxChilds]; is baseClass allChilds[maxChilds];. The chain should be the holder of the objects, so addChild(...) should not accept an instance of the child-class. It should create the instance and use (if necessary) std::move to add it to the array.
Remark: It will be easier for you using
std::vector<baseClass>allChilds;
allChilds.reserve(maxChilds); //reserves the memory but you can still use push back

How would you access derived methods using a base pointer ?

I have seen several posts on this topic, but did not find the kind of solution I am looking for. So sorry at the outset for yet another duplicate. But I want to know what you experts will do faced with a situation as given below ?
class Vehicle // A base class
{
public:
static Vehicle* CreateInstance(const int createWhat)
{
switch(createWhat)
{
case 1:
return new Segway();
break;
case 2:
return new Car();
break;
}
}
};
Now I have a couple of derived classes ..
class Segway : public Vehicle // Segway is a vehicle
{
};
class Sensor
class FuelConsumptionInfo;
class Car : public Vehicle // Car is a vehicle
{
public:
std::list<Sensor>& GetSensorList()
{
return m_pListOfSensors;
}
bool CompareThisCarAgainstOthers(std::list<Vehicle*>& vehicles) const
{
bool isMostEfficientCar = false;
std::list<Vehicle*>::iterator iterVal = vehicles.begin();
while(iterVal != vehicles.end())
{
// 1. Get the list of sensors of this car and compare against the sensors of this car ...
// 2. Get the fuel consumption information and compare against the fuel efficiency of this car ...
}
return isMostEfficientCar;
}
private:
std::list<Sensor*> m_pListOfSensors;
FuelConsumptionInfo* m_FuelEfficiency;
};
And finally I have my favourite car and a set of other cars, and I want to compare my car against them.
int main()
{
std::list<Vehicle*> listOfOtherCars;
Vehicle* pMyFavCar = Vehicle::CreateInstance(2);
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
listOfOtherCars.push_back(Vehicle::CreateInstance(2));
// How can I invoke the CompareThisCarAgainstOthers without:
// 1. Introducing any base class empty functions ..
// 2. Without using static/dynamic casting to convert the base pointer to a derived class pointer ...
}
As already mentioned in the comments, I want to invoke the CampareThisCarAgainstOthers, but I do not want to cast the base class pointer, nor do I want to introduce any virtual functions in the base class which I think defies the whole logic of having a base class. Even introducing empty virtual base functions will not help because GetSensorList returns a reference to the list.
I will be very thankful to your answers.
The only way to access a child method using a base pointer is by casting the base pointer to a child pointer. This has bad side effects (search the internet for "C++ object slicing").
One issue is that you don't know what kind of child / object the base pointer is pointing to. You could cast the pointer to a wrong child method. Example: a pointer to a Cruise Ship is passed to a function taking a pointer to vehicle. What happens when inside the function, the pointer is cast to a Bicycle type. Clearly, not the same vehicle.
All you can safely access with a pointer to a base class is the public methods and members of the base class. No more, no less.
For example, given a base class of Car and some child classes such as Model_T, Tesla, Hybrid and Mustang, and a pointer to a Car instance, you don't know what kind of car the child is. A Model_T is different than an electric Tesla. A Mustang with a gasoline engine is different than a Hybrid with both electric and gasoline engines.
If you want to access functionality using a base class pointer, put the functionality into the base class as an abstract function. The Car class could have a method virtual bool has_electric_engine(void) const = 0;. The Model_T and Mustang would return false.
Please don't make virtual equality methods into a base class because the code will be comparing attributes, but you really want to compare types. In the example, the Mustang car does not have all the same attributes as the Model_T. Usually, if you need to compare types, your design is flawed.

C++ copy constructor issue with parent/child classes

I've run into a problem with copy constructors...I assume there is a basic answer to this and I'm missing something obvious - maybe I'm doing something entirely wrong - but I haven't been able to figure it out.
Basically, I have a parent class and child class. The parent class contains a vector of pointers to a (different) base class object. The child class wants to instead store pointers to objects derived from that base object.
Here's a pseudocode sample, if that helps:
// Base classes
class ItemRev {
...
}
class Item {
protected:
vector<ItemRev *> m_revPtrVec;
}
Item::Item(const Item &inputItemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin();
while (vecIter != (inputItemObj.m_revPtrVec).end()) {
(this->m_revPtrVec).push_back(new ItemRev(**vecIter));
}
}
=========
// Derived classes
class JDI_ItemRev : public ItemRev {
...
}
class JDI_Item : public Item {
...
}
JDI_Item::JDI_Item(const JDI_Item &itemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin();
// The below does not work!
while (vecIter != (inputItemObj.m_revObjPtVec).end()) {
m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter));
}
}
The problem with the above is in the push_back() call in the JDI_Item copy constructor.
Given this setup, what should the child class's copy constructor look like? Do I even need a child class copy constructor? I assumed I did, because the copy constructor is creating new objects, and the parent copy constructor will create new objects that are not the type I want in the derived class (i.e., the parent object stores pointers to ItemRev objects, while the child object should store pointers to derived JDI_ItemRev objects).
As mentioned in the comments, there is probably a more succinct way to express this problem (i.e. your class structure needs some work).
However, if you want to do it this way, the easiest way to achieve it is to use a virtual clone() method in the base class of ItemRev, with overrides of it defined in derived classes.
e.g.:
class ItemRev {
virtual ItemRev* clone() const = 0;
};
class JDI_ItemRev : public ItemRev {
ItemRev* clone() const override
{
// do your actual cloning here, using the copy constructor
return new ItemRev(*this);
}
};
Now, whenever you call clone() on any class derived from ItemRev, you will be returned an ItemRev* but it will point to a fully constructed derived class. You can of course get to the derived class's interface with static_cast<> or dynamic_cast<>.
...however...
derivation often seems like an easy win but it often turns out not to be. Inheritance should only be used if the derived class really is a type of the base class. Often people select inheritance when the derived class is a lot like a base class, or shares many characteristics with a base class. This is not the time to use inheritance. It's the time to use encapsulation.
In general, inheritance is evil.
On another note, you might find this link interesting.
Presentation on inheritance as an implementation detail

How do you pass a derived class if you only know the base class?

I apologize in advance as I am a beginner in OO-programming.
I have a base class called Hero, with three derived classes Archer, Warrior, and Mage. The user is prompted to select one of them, and an object of the appropriate derived class is created. They have different initial values and member functions, and the next step is to pass this object to another function.
Let's say the function is called battle(), and it takes the object as an argument. How do I go about doing this? Do I have to create three separate battle() or is there a way to pass the object without the need to specify the derived class?
void Hero::init(string job)
{
if (job == "archer")
Archer archer;
else if (job == "mage")
Mage mage;
else
Warrior warrior;
battle(); // What to put as argument?
}
battle() should take a reference or (smart) pointer to the base class as an argument. For example:
void battle(std::shared_ptr<Hero> ptr);
And your argument should be a smart pointer as well:
void Hero::init(const std::string& job)
{
std::shared_ptr<Hero> ptr;
if (job == "archer")
ptr = std::make_shared<Archer>();
else if (job == "mage")
ptr = std::make_shared<Mage>();
else
ptr = std::make_shared<Warrior>();
battle(ptr);
}
std::shared_ptr is a smart pointer class that encapsulates dynamic memory allocation and resource acquisition for a pointer. This is so that we don't have to write new every where. Moreover, when the smart pointer is destroyed (meaning no more copies of ptr exist, if any) then delete is called on the contained Hero pointer.
The above works because all three classes are derived from Hero so the addresses of those derived class pointers can be pointed to by the base class.
No, you don't have to create 3 different battle functions, avoiding this is precisely the purpose of inheritance.
You can create a single battle function:
void battle(Hero& hero)
{
}
You can call it as follows:
battle(archer);
battle(mage);
battle(warrior);
but you will need to create your heros in another way, because as they are created now, they fall out of scope as soon as the if or else are done.
This is where you should use run-time polymorphism.
Instead of creating local derived class object instances, create a base class pointer and point it to the derived class instance:
Hero* hero = new Archer();
Hero* hero = new Mage();
Hero* hero = new Warrior();
Then you could pass base class pointer Hero* to your method battle
battle(hero)
The signature of your method would be:
void battle(Hero* )
This means, battle method can accept any kind of Hero at run-time, be it an archer, mage or a warrior.