如何正确转换派生类
How to properly cast my derived class?
我有一个基类(car
)和一个继承基类(honda
):
class car
{
virtual void polymorphic_class()
{ }
};
class honda : public car
{ };
当我使用以下代码并强制转换我的类时,会得到一个空指针:
list<car> cars;
honda h;
cars.push_back(h);
honda* h_ptr = dynamic_cast<honda*>(&cars.back());
// h_ptr is NULL
为什么?我必须如何正确投射我的对象?
这不起作用的原因是对象切片。cars
中的物体不再是honda
,而只是汽车。
您需要一个指针或智能指针的向量:
list<car*> cars;
honda h;
cars.push_back(&h);
honda* h_ptr = dynamic_cast<honda*>(cars.back());
我实际上会改变设计并car
抽象(纯粹的虚拟析构函数或其他东西)。这样,您还会收到编译错误。
多态性适用于指针和引用,而不是对象实例。
在这种情况下,列表包含类型 car
的对象,而不是任何派生类型的对象。当您插入honda
时,它将复制car
部分并忽略其余部分;这有时称为切片。
对于多态性,您可以使用指针列表:
list<car*> cars {new honda};
honda * h_ptr = dynamic_cast<honda*>(cars.back()); // should be a valid pointer
注意:如果您确实像我的示例那样使用new
进行分配,请记住delete
它们,或者存储智能指针(如std::unique_ptr<car>
)而不是原始指针。还需要一个虚拟析构函数才能使用基类指针删除对象。
你可以通过使基类抽象来避免切片问题;如果它包含纯虚函数,那么你不能实例化该类型的对象,只能实例化重写这些函数的派生类型的对象:
class car
{
virtual ~car() {}
virtual void do_something() = 0;
};
class honda : public car
{
void do_something() {}
};
如果你实际上不想要一个抽象接口(例如,如果你只使用dynamic_cast
而不是通过虚函数访问派生类功能),那么你可以使析构函数成为纯虚拟的;那么派生类就不必显式覆盖任何东西。基类析构函数仍然必须实现,并且由于语言的怪癖,该实现必须在类定义之外:
class car
{
virtual ~car() = 0;
};
inline car::~car() {}
class honda : public car {};
这是一种有点不寻常的方法,因为通过虚函数的多态性通常更有效、更方便。
试试这个
list<car*> cars;
honda *h = new honda();
cars.push_back(h);
honda* h_ptr = dynamic_cast<honda*>(cars.back());
这行得通。
相关文章:
- 存储模板类型以强制转换回派生<T>
- 在 C++ 中将对象转换为派生类型
- 从基类实例调用派生类方法而不进行强制转换
- 从基指针到派生的强制转换问题
- C++将派生类转换为基类时'object slicing'期间发生的情况
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 为什么从基转换为派生提供此功能?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 从从该抽象类派生的 Python 对象强制转换C++抽象类C++
- 基类到派生类的强制转换向量
- 有没有办法复制派生类指针的向量而不将其强制转换为基类?
- 为什么此代码不将基类强制转换为 c++ 中的派生类?
- 如何在运行时将指向派生类的 void* 正确转换为指向基类的 void*
- 从基类的共享指针向下转换到派生类的引用
- 为了访问方法,从基类动态转换为派生类
- 如何将矢量<派生*>转换为矢量<Base*时避免复制>