这是我的问题:我正在制作一个C ++ DLL,它广泛依赖于实例对象导出。 所以我通过一些导出的工厂方法返回我的实际实例作为接口的指针。
我使用的接口纯粹是虚拟的,以避免链接问题。所以我也需要一个纯粹的虚拟析构函数,并且我实现了一个(使用空体,因为我用Google搜索它)。 所有编译完全正常,除了...我无法看到是否调用了实际的析构函数 - 因为当我添加一些
std::cout << "hello destructor";时,我永远不会看到它。
我有一些明确的“删除obj”(编辑:它是从DLL里面的“FreeObject”方法调用的),这不是问题。
我错过了什么吗?有没有其他方法可以通过界面删除我的对象?
编辑:同样,我没有内存管理不一致,它都在DLL内部。但是没有调用正确的析构函数。
答案 0 :(得分:4)
您不应该跨越DLL边界混合和匹配new
和delete
的调用。
相反,我建议使用COM使用的经过验证的方法:AddRef
和Release
。当引用计数达到零时,Release
会从DLL内部调用delete this;
,确保匹配new
和delete
。
答案 1 :(得分:1)
这就是我为动态加载的C ++类解决特定问题的方法 -
拥有所有可插入对象的基类,即
class object_t {
public:
virtual ~object_t();
//other type utils...
};
为所有插件接口提供基本接口,即
class object_t;
class interface_t {
public:
virtual object_t* object() = 0;
}
object_t将具有链接,在其自己的dll中定义它,您将链接插件类。在object_t中有其他有用的钩子是复制,产生,RTTI和其他类型的工具,我的基础对象有例如spawn(),copy(),object_name()。
因此,所有具体类都派生自object_t及其各自的纯虚拟接口类型,所有已发布(可插入)的接口都派生自interface_t。
然后你可以加载一个插件,使用你的工厂实例化界面并删除 -
delete interface->object()
由于object_t有一个虚析构函数,因此将调用正确的析构函数。
如果所有插件/可执行文件都链接到相同的动态(dll)CRT,那么在linux下删除对象的位置没有问题,如果所有插件/可执行文件都链接在一起,那么它在窗口下是很好的。
答案 2 :(得分:0)
根本不需要界面中的析构函数。只有delete
调用者才能看到正确的析构函数。在DLL之外,使用接口指针作为句柄,而不是你可以创建/销毁的东西。对象构造/销毁应该在DLL内部。您可以使用引用计数或任何其他技术,只需提供适当的导出来访问和操作对象,您可以决定将封装多少内存管理。