C++ 多态性++;使用纯虚函数析构函数
我不确定下面的代码是否可以防止内存泄漏C++ 多态性++;使用纯虚函数析构函数,c++,qt,C++,Qt,我不确定下面的代码是否可以防止内存泄漏 #ifndef RENDERABLE_H #define RENDERABLE_H class QGLShaderProgram; class GLWidget; class BoundingBox; class Renderable{ public: virtual void update(float duration) = 0; virtual void render(QGLShaderProgram& shader, f
#ifndef RENDERABLE_H
#define RENDERABLE_H
class QGLShaderProgram;
class GLWidget;
class BoundingBox;
class Renderable{
public:
virtual void update(float duration) = 0;
virtual void render(QGLShaderProgram& shader, float duration) = 0;
virtual BoundingBox* getBBox() const = 0;
virtual void translate(float xx, float yy, float zz) = 0;
virtual void rotate(float degrees_x, float degrees_y, float degrees_z) = 0;
virtual void scale(float xx, float yy, float zz) = 0;
};
#endif // RENDERABLE_H
上述“接口”由object3d.cpp实现。然后,如果多个Object3D对象属于同一场景,我们可以将它们添加到场景对象中。但是,在场景结束时,我希望确保没有内存泄漏,因此我会调用delete来删除所有内容。但是,在场景对象中,我有以下变量:
QVector<Renderable*>* sceneObjects;
QVector<GLTexture2D*>* sceneTextures;
QMap<QString, Material*>* sceneMaterials;
应该删除QVector,根据Qt,它应该调用其中那些对象的析构函数。然而,Qt文档并不清楚对象指针。Qt会用适当的析构函数删除对象指针吗?此外,可渲染指针会发生什么情况?从“接口”可以看出,它没有析构函数
谢谢你的意见。
首先,您的
Renderable
类必须具有虚拟析构函数,因为在指向派生对象的基指针上调用delete
是未定义的行为
其次,不需要,您需要在每个指针上循环调用delete
(或者,只要容器中的每个对象都分配了普通new
(而不是new[]
或malloc
或任何其他内容),以确保它们的内存被回收(Qt如何知道指针是否指向由new
分配的对象?它们可以指向由new[]
分配的对象、堆上的对象、堆栈或其他地方)
如果您不想这样做,您可以将
unique_ptr
s存储在容器中,然后当您delete
容器时,将调用unique_ptr
s的析构函数,这些析构函数将解除分配它们所拥有的内存。无需手动解除分配它们或首先使用qdeletall
总之,您的Renderable
类必须有一个虚拟析构函数,因为在指向派生对象的基指针上调用delete
是未定义的行为,没有虚拟析构函数
其次,不需要,您需要在每个指针上循环调用delete
(或者,只要容器中的每个对象都分配了普通new
(而不是new[]
或malloc
或任何其他内容),以确保它们的内存被回收(Qt如何知道指针是否指向由new
分配的对象?它们可以指向由new[]
分配的对象、堆上的对象、堆栈或其他地方)
如果您不想这样做,您可以将
unique_ptr
s存储在容器中,然后当您delete
容器时,将调用unique_ptr
s的析构函数,这些析构函数将释放它们拥有的内存。无需手动释放它们或使用所需的qdeletall
手动删除每个指针。不过,您不需要手动迭代每个指针。您可以使用以下工具轻松完成此操作:
qDeleteAll(*sceneObjects);
delete sceneObjects;
其他容器也是如此。qDeleteAll
记录在这里:
正如Seth Carnegie所提到的,还可以添加一个虚拟dtor。您需要手动删除每个指针。不过,您不需要手动迭代每个指针。您可以使用以下工具轻松完成此操作:
qDeleteAll(*sceneObjects);
delete sceneObjects;
其他容器也是如此。qDeleteAll
记录在这里:
正如Seth Carnegie所提到的那样,还要添加一个虚拟dtor。所以我猜析构函数也必须是纯虚拟的?@ChaoSXDemon不是纯虚拟的,只是虚拟的。你可以将它设为纯虚拟的,但这没有任何意义,而且它必须有一个定义。我应该在我的实现对象中写些什么,这样对于w/e对象,它就是using Renderable它将调用正确的析构函数?@ChaoSXDemon它将自动调用正确的析构函数,您不需要手动调用它们。但是您必须在
Renderable
中显式地编写一个虚拟析构函数,即使它是空的。所以我猜析构函数也必须是纯虚拟的?@ChaoSXDemon不是纯虚拟的,只是虚拟的.Y你可以让它成为纯虚拟的,但这没有任何意义,而且它必须有一个定义。我应该在我的实现对象中写些什么,这样对于使用Renderable的w/e对象,它将调用正确的析构函数?@ChaoSXDemon它将自动调用正确的析构函数,你不需要手动调用它们。但是y您必须在Renderable
中显式地编写一个虚拟项目,即使它是空的。谢谢,它现在工作正常。但是,QVector rItems似乎找不到我的项目。假设我有:Renderable*o1=new Object3D(),稍后我调用(在rItems.append(o1)之后),rItems.remove(rItems.indexOf(o1))它给了我超出范围的索引数组。具体地说,返回的索引是-1。你知道为什么吗?@ChaoSXDemonindexOf()
在找不到元素时返回-1。这是它告诉你“找不到”的唯一方法。(记住,Qt不使用异常处理。)您不应该仅仅将其返回值用作索引;首先检查<0
。谢谢,它现在工作正常。但是,QVector rItems似乎无法找到我的项目。假设我有:Renderable*o1=new Object3D(),稍后我调用(在rItems.append(o1)之后),rItems.remove(rItems.indexOf(o1))它给了我超出范围的索引数组。具体地说,返回的索引是-1。你知道为什么吗?@ChaoSXDemonindexOf()
在找不到元素时返回-1。这是它告诉你“找不到”的唯一方法。(记住,Qt不使用异常处理。)您不应该仅将其返回值用作索引;首先检查<0
。