在C ++中调用虚拟析构函数的顺序

SYNcoder

好吧,我一直试图通过C ++理解OOP概念,但是我无法获得虚拟析构函数的某些部分。

我写了一个小片段:

class A{
    int x;
public: 
    virtual void show(){
        cout << " In A\n"; 
    }
    virtual ~A(){
        cout << "~A\n";
    };
};

class B: public A{
    int y;
public: 
    virtual void show(){
        cout << " In B\n"; 
    }
    virtual ~B(){
        cout << "~B\n";
    };
};

class C: public A{
    int z;
public: 
    virtual void show(){
        cout << " In C\n"; 
    }
    virtual ~C(){
        cout << "~C\n";
    };
};
class E: public A{
    int z;
public: 
    virtual void show(){
        cout << " In E\n"; 
    }
    virtual ~E(){
        cout << "~E\n";
    };
};

class D: public B , public C , public E{
    int z1;
public: 
    virtual void show(){
        cout << " In D\n"; 
    }
    virtual ~D(){
        cout << "~D\n";
    };
};

signed main(){
    // A * a = new A();
    // B *b = new B();
    D *d = new D();
    B *b = d;
    C *c = d;
    E * e = d;
    A * a = new A();
    cout << d << "\n";
    cout << b  << "\n";
    cout  << c << "\n";
    cout << e << "\n";
    delete b;
    // a -> show();

}

在运行代码时,我得到的结果为:

0x7f8c5e500000
0x7f8c5e500000
0x7f8c5e500018
0x7f8c5e500030
~D
~E
~A
~C
~A
~B
~A

现在三个问题:

  • 根据Wikipedia文章virtual_table,对象c的地址比d和b的地址多8个字节,这在e情况下会发生。
  • 当我调用delete b而不是delete d时,也会获得相同顺序的虚拟析构函数,所以为什么派生类析构函数称为
  • 仅当我删除对象时,才调用虚拟析构函数,然后在程序结束时删除vtable和vpointers(当我运行代码而不delete d执行时,就停止执行而不打印任何内容)。
彼得-恢复莫妮卡

您的问题顺序如下:

(1)是的,指向具有多重继承的派生类的对象的基址的指针与指向最派生类型的指针相比可能会更改其数值。原因是基类是派生类的一部分,非常像成员,位于偏移处。仅对于多继承中的第一个派生类,此偏移量可以为0。这就是为什么无法使用简单的强制转换此类指针的原因reinterpret_cast()

(2)b指向,E后者也是-an A

正是这virtual对成员函数意味着什么:编译器生成的代码检查运行时指向的对象,并调用为该对象的实际类型(是E定义的函数,而不是该对象的类型。用于访问该对象的表达式(为B)。表达式的类型在编译时完全确定; 实际完整对象的类型不是。

如果未声明虚拟的析构函数,则程序可能会按预期运行:编译器将创建代码,该代码仅调用针对表达式类型(for B定义的函数,而无需任何运行时查找。非虚拟成员函数调用效率稍高;但是对于像您这样的析构函数,通过基类表达式进行销毁时,行为是不确定的如果您的析构函数是公共的,则它应该是虚拟的,因为这种情况可能会发生。

Herb Sutter写了一篇有关虚拟函数的文章,其中包括虚拟析构函数,值得一读。

(3)内存(包括动态分配的内存)被释放,并且在程序退出后,现代标准操作系统可以再次将其用于其他用途。(如果旧的操作系统或独立的实现提供动态分配,则可能不是这种情况。)但是,不会调用动态分配的对象的析构函数,如果它们拥有数据库或网络连接之类的资源,则可能会出现问题。最好释放。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章