多态性:调用不带指针的重写函数
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();
我正在用 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();