多态性:调用不带指针的重写函数

polymorphism: calling overrided functions without pointers

我正在用 C++ 做一些实验。 我对多态性的一些行为印象深刻。 在其他语言中(例如 c#),当我将基于派生 class 的对象分配给 BaseType 的对象时:该对象开始使用派生 class 代码。或者,如果我有一个 BaseType 对象列表,并将派生的基于 class 的对象放入其中:每个元素都根据特定类型工作。 在 C++ 中没有... 我只是使用指针在 C++ 中获得了这种行为。 有替代方法吗?我错过了什么吗? 这是我的代码示例:



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;

}

例如,在 C# 中,尽管显式转换为基础 class,但仍会调用覆盖的方法:(BaseClass)InherithedClassObject.method() 调用覆盖的方法,而不是基础方法。 在列表的迭代中:重写的方法也被调用(总是 C#)。

在c++中,我是否必须始终使用指针以确保具有多态行为的可能性?结果:我是否必须始终管理显式破坏对象的内存分配?

当您将 Ferrari 放入您的第一个列表时,您遇到了 type erasure - "GenericCar" 结构被复制到列表中,任何可以识别它是 "FerrariCar" 的东西都丢失了.

您需要一个指针或引用来调用多态函数,有一个指针或引用可以让您访问对象的 virtual table

要有一个可以存储此类汽车对象并传递给不同函数的列表,您可能需要使用智能指针,这样您就不会遇到悬空指针或内存泄漏。

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