如何正确删除从另一个 DLL 接收到的派生对象?
How can I properly delete a derived object I received from another DLL?
在我的场景中,我有一个带有基础 class 的 DLL。这个 DLL 可以加载插件。每个插件 DLL 导出一个创建函数,该函数 returns 一个派生对象。我希望插件 DLL 中的对象可以自行删除。
在下面,我记下了两种方式。请忽略缺失的 public/private 语句。第一种方式当然更简单,因为我只需要像往常一样调用delete,但我不确定是否有效。第二种方式显式 delete this
因为 this
必须有派生类型,对吗?
// main DLL
class Base1
{
virtual ~Base(){}
};
class Base2
{
virtual ~Base(){}
virtual void destroy() = 0;
};
// plugin DLL without destroy
class Derived1 : public Base1
{
Derived1()
{
m_p = new cSomeClass;
}
virtual ~Derived1()
{
delete m_p;
}
cSomeClass * m_p;
}
// function which is exported
Base1 * createDerived1()
{
return new Derived1;
}
// plugin DLL with destroy
class Derived2 : public Base2
{
Derived2()
{
m_p = new cSomeClass;
}
virtual ~Derived2()
{
delete m_p;
}
virtual void destroy()
{
delete this;
}
cSomeClass * m_p;
}
// function which is exported
Base2 * createDerived2()
{
return new Derived2;
}
int main()
{
Base1 * pBase1 = createDerived1();
delete pBase1;
pBase = nullptr;
// is derived object properly deleted?
Base2 * pBase2 = createDerived2();
pBase2->destroy();
pBase2 = nullptr;
// is derived object properly deleted?
}
哪个 "the right thing",即使用基 class 指针正确删除派生对象?
delete
知道对象类型并且会因为虚拟析构函数而正确删除它。
- 写一个纯虚拟的 destroy 方法,在派生的 classes 中实现。
- 在 create 方法旁边导出 destroy() 方法,该方法采用
Base
指针并在 delete
之前进行动态转换。 (这个案例我没有写例子,因为我觉得它没有吸引力。)
第一种方法似乎是最简单的,因为它除了正确编写虚拟析构函数外不需要任何工作。
DLL 之间的内存管理是一个真正的痛苦。
一般来说,在一个 DLL 中分配的内存不得在另一个 DLL 中释放。
典型的解决方案是提供显式销毁 (delete this
) 函数,当对象不再需要时必须调用该函数。
所以选择 2(编写一个在派生 类 中实现的纯虚拟销毁方法):
class IBase
{
public:
virtual void destroy() = 0;
// Other pure virtual methods.
};
class Derived : public IBase
{
public:
Derived() { m_p = new cSomeClass; }
virtual ~Derived() { delete m_p; }
virtual void destroy() override { delete this; }
private:
cSomeClass *m_p;
};
extern "C" __declspec(dllexport) IBase * __cdecl createDerived()
{
return new Derived;
}
有关详细信息,您可以阅读 GREAT Exporting C++ classes from a DLL(来自 Eli Bendersky 的网站)。
不需要在子 classes 中单独删除函数。更新到 manlio post:
// 在 header
中定义 abstaract class 和 func
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
class CLASS_DECLSPEC IBase
{
public:
// implement function in parent class
void destroy(){delete this;};
virtual ~IBase(){};
// Other pure virtual methods.
};
//导入dll源头文件
class Derived : public IBase
{
public:
Derived() { m_p = new cSomeClass; }
virtual ~Derived() { delete m_p; }
private:
cSomeClass *m_p;
};
extern "C" __declspec(dllexport) IBase * __cdecl createDerived()
{
return new Derived;
}
在我的场景中,我有一个带有基础 class 的 DLL。这个 DLL 可以加载插件。每个插件 DLL 导出一个创建函数,该函数 returns 一个派生对象。我希望插件 DLL 中的对象可以自行删除。
在下面,我记下了两种方式。请忽略缺失的 public/private 语句。第一种方式当然更简单,因为我只需要像往常一样调用delete,但我不确定是否有效。第二种方式显式 delete this
因为 this
必须有派生类型,对吗?
// main DLL
class Base1
{
virtual ~Base(){}
};
class Base2
{
virtual ~Base(){}
virtual void destroy() = 0;
};
// plugin DLL without destroy
class Derived1 : public Base1
{
Derived1()
{
m_p = new cSomeClass;
}
virtual ~Derived1()
{
delete m_p;
}
cSomeClass * m_p;
}
// function which is exported
Base1 * createDerived1()
{
return new Derived1;
}
// plugin DLL with destroy
class Derived2 : public Base2
{
Derived2()
{
m_p = new cSomeClass;
}
virtual ~Derived2()
{
delete m_p;
}
virtual void destroy()
{
delete this;
}
cSomeClass * m_p;
}
// function which is exported
Base2 * createDerived2()
{
return new Derived2;
}
int main()
{
Base1 * pBase1 = createDerived1();
delete pBase1;
pBase = nullptr;
// is derived object properly deleted?
Base2 * pBase2 = createDerived2();
pBase2->destroy();
pBase2 = nullptr;
// is derived object properly deleted?
}
哪个 "the right thing",即使用基 class 指针正确删除派生对象?
delete
知道对象类型并且会因为虚拟析构函数而正确删除它。- 写一个纯虚拟的 destroy 方法,在派生的 classes 中实现。
- 在 create 方法旁边导出 destroy() 方法,该方法采用
Base
指针并在delete
之前进行动态转换。 (这个案例我没有写例子,因为我觉得它没有吸引力。)
第一种方法似乎是最简单的,因为它除了正确编写虚拟析构函数外不需要任何工作。
DLL 之间的内存管理是一个真正的痛苦。
一般来说,在一个 DLL 中分配的内存不得在另一个 DLL 中释放。
典型的解决方案是提供显式销毁 (delete this
) 函数,当对象不再需要时必须调用该函数。
所以选择 2(编写一个在派生 类 中实现的纯虚拟销毁方法):
class IBase
{
public:
virtual void destroy() = 0;
// Other pure virtual methods.
};
class Derived : public IBase
{
public:
Derived() { m_p = new cSomeClass; }
virtual ~Derived() { delete m_p; }
virtual void destroy() override { delete this; }
private:
cSomeClass *m_p;
};
extern "C" __declspec(dllexport) IBase * __cdecl createDerived()
{
return new Derived;
}
有关详细信息,您可以阅读 GREAT Exporting C++ classes from a DLL(来自 Eli Bendersky 的网站)。
不需要在子 classes 中单独删除函数。更新到 manlio post:
// 在 header
中定义 abstaract class 和 func#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
class CLASS_DECLSPEC IBase
{
public:
// implement function in parent class
void destroy(){delete this;};
virtual ~IBase(){};
// Other pure virtual methods.
};
//导入dll源头文件
class Derived : public IBase
{
public:
Derived() { m_p = new cSomeClass; }
virtual ~Derived() { delete m_p; }
private:
cSomeClass *m_p;
};
extern "C" __declspec(dllexport) IBase * __cdecl createDerived()
{
return new Derived;
}