多继承下虚函数深析,第二基类虚析构必加

// project100.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <time.h >
#include <stdio.h>
#include <vector>

using namespace std;

class Base
{
    
    
public:
    virtual void f() {
    
     cout << "Base::f()" << endl; }
    virtual void g() {
    
     cout << "Base::g()" << endl; }
    virtual void h() {
    
     cout << "Base::h()" << endl; }   

    virtual ~Base() {
    
    
        int abc;
        abc = 1;
    }

};

class Base2
{
    
    
public:
    virtual void hBase2() {
    
    

        cout << "Base2::hBase2()" << endl;
    }

    virtual ~Base2()    {
    
    
        int abc;
        abc = 1;
    }
};

class Derive :public Base,public Base2 {
    
    
public:
    virtual void i() {
    
     cout << "Derive::i()" << endl; }
    virtual void g() {
    
     cout << "Derive::g()" << endl; }
    void myselffunc() {
    
    } //只属于Derive的函数

    virtual ~Derive() {
    
    
        int abc;
        abc = 1;
    }   
};
int main()
{
    
       
    //一:多继承下的虚函数
    //多重继承复杂性体现在后边这个基类上;
    Base2 *pb2 = new Derive();
    //编译器视角
    //Derive *temp = new Derive();
    //Base2 *pb2 = temp + sizeof(Base); // sizeof(Base) * sizeoeof(Base2);
    //Base2 *pb2 = (Base2 *)((char *)temp + sizeof(Base));
    
    //先转char* 才是加1个字节。
    delete pb2;

    //二:如何成功删除用第二基类指针new出来的继承类对象
    //a)我们要删除的实际是整个Derive()对象
    //b)要能够保证Derive()对象的析构函数被正常调用
    //c)编译器会调用Base2的析构函数,还是调用Derive的析构函数呢?
    //d)执行delte pb2时,系统的动作会是?
      //d.1)如果Base2里没有析构函数,编译器会直接删除以pb2开头的这段内存,一定报异常,因为这段内存压根就不是new起始的内存;
      //d.2)如果Base2里有一个析构函数,但整个析构函数是个普通析构函数(非虚析构函数),那么当delte pb2,
          //这个析构函数就会被系统调用,但是delete的仍旧是pb2开头这段内存,所以一定报异常。因为这段内存压根就不是new起始的内存;
            //析构函数如果不是虚函数,编译器会实施静态绑定,静态绑定意味着你delete Base2指针时,删除的内存开始地址就是pb2的当前位置;所以肯定是错误的
      //d.3)如果Base2里是一个虚析构函数,   
         //~Dervice()
            //~Base2()
            //~Base()
     //d.4)Derive里就就算没有虚析构函数,因为Base2里 有虚析构函数,编译器也会为此给Derive生成虚析构函数,为了调用~Base2()和~Base()虚析构函数;
    //e)建议,凡是涉及到继承的,所有类都要求大家些虚析构函数;

    Base *pbm = new Base();
    Base2 *pb222 = new Base2();
    Derive *p11212 = new Derive();

    p11212->g();
    p11212->i(); //走虚函数表

    Derive dddd;
    dddd.i(); //直接调用虚函数

    //Derive 类的第二个虚函数表中发现了thunk字样:
    //一般这玩意用在多重继承中(从第二个虚函数表开始可能就 会有);用于this指针调整。这玩意其实是一段汇编代码,这段代码干两个事情:
    //(1)调整this指针
    //(2)调用Derive析构函数
    return 1;
}

//vs2017单步调试的一些结果

delete pb2;

00F230BD  call        edx 
00F210AA  jmp         Derive::`vector deleting destructor' (0F22878h)  

00F22878  sub         ecx,4   调整this指针,指向了Derive对象首地址 **********************
00F2287B  jmp         Derive::`vector deleting destructor' (0F210D2h) 
00F210D2  jmp         Derive::`scalar deleting destructor' (0F22970h)
00F22996  call          Derive::~Derive (0F2141Ah)  
00F2141A  jmp         Derive::~Derive (0F22580h)  
    00F225EC  call         Base2::~Base2 (0F212DFh)
    00F225F4  call         Base::~Base (0F212E9h) 
00F229A9  call        operator delete (0F212EEh) 

猜你喜欢

转载自blog.csdn.net/qq_38158479/article/details/112080234