编译器将派生实例强制转换为父抽象类



我在一个项目中遇到了一个错误,我正在尝试使用抽象类。我有一个抽象类定义如下:

class BoundingVolume: public Displayable{
public:
virtual bool intersects(BoundingVolume const& bv) const noexcept = 0;
virtual bool intersects(Sphere const& sp)const noexcept = 0;
virtual bool intersects(AABB const& aabb) const noexcept= 0;
virtual float getVolume() = 0;
virtual std::tuple<std::vector<std::array<float,3>>, std::vector<std::vector<unsigned int>>> &toMesh() = 0;
};

我把它作为另一个类的成员使用,因为在那个类中我不知道我想使用它的派生类:

class Object{
public :
explicit Object(std::vector<Point> const& vertices) noexcept;
std::vector<Point> m_vertices;
BoundingVolume *m_bounding_volume;
};

我的Object构造函数的代码:

m_vertices = vertices
AABB aabb(points); // AABB is a derived class of BoundingVolume
auto aabb_pt = (AABB*) malloc(sizeof(AABB));
*aabb_pt = aabb;
m_bounding_volume = aabb_pt;

问题是,当我构造Object的实例并在其BoundingVolume成员上调用toMesh时,程序崩溃(退出代码139(。在调试时,这似乎是因为编译器在构造函数的最后一行进行了强制转换,这不允许它稍后理解m_bounding_volume是派生类的实例。我做错了什么?我对每件事都理解正确吗?应该改变什么?

您不应该使用malloc为此类分配内存。在C++中,对象可能需要额外的逻辑来构造,而这些逻辑不是由malloc封装的,尤其是对于具有继承性的对象来说,这是非常正确的,因为[在大多数常见的实现中]编译器必须做隐藏的工作来构造保存其类型信息所需的额外成员数据。

在C++中,应该使用new关键字:

m_vertices = vertices
AABB aabb(points); // AABB is a derived class of BoundingVolume
auto aabb_pt = new AABB(aabb); //Assuming that you do intend to allocate a copy of aabb, and not merely point to it
//If you just wanted a pointer to aabb, this would be more appropriate
//auto aabb_pt = &aabb;
m_bounding_volume = aabb_pt;

在C++中,最好使用智能指针,如std::unique_ptrstd::shared_ptr/std::weak_ptr,因为它们允许您表达所有权语义,并有助于防止此类错误。

最新更新