问题
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?
回答1:
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();
来源:https://stackoverflow.com/questions/59446108/polymorphism-calling-overrided-functions-without-pointers