C++虚拟析构函数
C++ virtual destructor
问题基于以下类层次结构。
Base2* d3 = new Der3();
d3->v1();
delete d3;
输出为:
Base1
Base1
Der1
Base2
Der3
v1 Base2
~Base2
我有个例外。为什么?(只应生成内存泄漏)
class Base1
{
public:
Base1() {std::cout << "Base1" << std::endl; }
~Base1() {std::cout << "~Base1" << std::endl; }
virtual void v1() { std::cout << "v1 Base1" << std::endl; }
void v2() {std::cout << "v2 Base1" << std::endl;}
void v3() {std::cout << "v3 Base1" << std::endl;}
};
class Base2
{
public:
Base2() {std::cout << "Base2" << std::endl; }
~Base2() {std::cout << "~Base2" << std::endl; }
void v1() { std::cout << "v1 Base2" << std::endl; }
void v2() {std::cout << "v2 Base2" << std::endl;}
void v3() {std::cout << "v3 Base2" << std::endl;}
};
class Der1 : public Base1
{
public:
Der1() {std::cout << "Der1" << std::endl; }
~Der1() {std::cout << "~Der1" << std::endl; }
virtual void v1() { std::cout << "v1 Der1" << std::endl; }
virtual void v2() {std::cout << "v2 Der1" << std::endl;}
void v3() {std::cout << "v3 Der1" << std::endl;}
};
class Der2 : public Base1,public Der1
{
public:
Der2() {std::cout << "Der2" << std::endl; }
~Der2() {std::cout << "~Der2" << std::endl; }
virtual void v1() { std::cout << "v1 Der2" << std::endl; }
void v2() {std::cout << "v2 Der2" << std::endl;}
void v3() {std::cout << "v3 Der2" << std::endl;}
};
class Der3 : public Base1,public Der1,public Base2
{
public:
Der3() {std::cout << "Der3" << std::endl; }
~Der3() {std::cout << "~Der3" << std::endl; }
virtual void v1() { std::cout << "v1 Der3" << std::endl; }
void v2() {std::cout << "v2 Der3" << std::endl;}
void v3() {std::cout << "v3 Der3" << std::endl;}
};
为什么说只应该得到内存泄漏?这是未定义的行为;任何事情都有可能发生。
问题可能是因为虚拟析构函数还用于确定释放函数和传递给它的地址。在您的情况下,您最终会将错误的地址传递给::operator delete
。但这正是实践中可能发生的事情。这是未定义的行为,任何事情都可能发生。
如果计划从类派生并使用指向基类的指针来删除对象,则必须声明它是析构函数虚拟的。否则,它就是未定义的行为。
class A
{
public:
~A() {}
...
};
class B : public A
{
public:
~B() {}
...
};
class C
{
public:
virtual ~C() {}
...
};
class D : public C
{
public:
virtual ~D() { }
...
};
B b; // OK, but bad practice
A* pa = new B; // not ok - when you try to delete
C* pc = new D; // ok
相关文章:
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 是否可以使用函数指针调用虚拟析构函数?
- 在没有动态内存的世界中,我是否需要虚拟析构函数?
- "虚拟""覆盖"析构函数
- 程序永远不会进入虚拟析构函数
- C++ std::vector 中的虚拟析构函数继承
- 哪种方法更适合处理虚拟析构函数?
- 拥有"受保护的非虚拟析构函数"与"受保护虚拟析构构函数"有什么好处
- 带有未解析外部元素的C++虚拟析构函数
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- 从内部类的析构函数调用虚拟函数
- C++切片和虚拟析构函数
- C++虚拟继承、虚拟析构函数和 dynamic_cast<void*>
- 添加虚拟析构函数会使代码大小膨胀
- 应该是虚拟析构函数吗?但是怎么做呢?
- 虚拟析构函数将对象移出 rodata 部分
- 为什么虚拟类的析构函数不会自动添加到 vtable 中?
- 如何将 std::unique_ptr<Parent> 与具有受保护虚拟析构函数的只读父类一起使用
- DIRECTX9 中自定义顶点的虚拟析构函数
- 声明析构函数虚拟就足够了吗?