继承体系下对象的构造顺序


#include "pch.h"
#include <iostream>
#include <vector>
#include <ctime>
#include<algorithm>

using namespace std;

namespace _nmsp1 //命名空间
{
    
    		
	//一:对象的构造顺序
	//二:虚函数的继续观察
	//千万不要在构造函数中你自己的代码中使用诸如memcpy或者直接操作等手段,来修改虚函数表指针的值,否则,调用虚函数时就可能造成系统崩溃;
	//三:构造函数中对虚函数的调用
	//某个类的构造函数 中 调用一个虚函数,那么走的不是虚函数表,而是直接调用。
	//四:举一反三


	class A
	{
    
    
	public:
		A()
		{
    
    
			printf("A this = %p\n", this);
			cout << "A::A()" << endl;
		}
		virtual ~A() {
    
    }
		virtual void myvirfunc() {
    
    }
		virtual void myvirfunc2() {
    
    }
	};

	class B:public A
	{
    
    
	public:
		B()
		{
    
    
			printf("B this = %p\n", this);
			cout << "B::B()" << endl;
		}
		virtual ~B() {
    
    }
		virtual void myvirfunc() {
    
    }
		virtual void myvirfunc2() {
    
    }
	};

	class C:public B
	{
    
    
	public:
		C():m_c(11)
		{
    
    
			//memcpy(this,)
			myvirfunc(); //构造函数中,这里没有走虚函数表,而是直接通过虚函数地址,直接调用这个虚函数(静态方式调用)
			printf("C this = %p\n", this);
			cout << "C::C()" << endl;
		}
		virtual ~C() {
    
    }
		virtual void myvirfunc() {
    
     myvirfunc2(); }
		virtual void myvirfunc2() {
    
    }
		int m_c;

	};
	//---------------------
	void func()
	{
    
    
		//C cobj;
		C *mycobj = new C();
		mycobj->myvirfunc(); //代码实现上的多态
				
			
	}
}

int main()
{
    
    
	_nmsp1::func();	
	return 1;
}

//单步调试,切到反汇编进行观察。

C cobj;
    C::C()   //末端类
        B::B()
            A::A()  //根源类
                vptr = A::vftable; //编译器插入的代码   34 9b 2f 01
                cout << "A::A()" << endl; //我们自己的代码
            vptr = B::vftable;   //编译器插入的代码  54 9b 2f 01            
            cout << "B::B()" << endl;  //我们自己的代码
        vptr = C::vftable;   //编译器插入的代码  3c 9b 2f 01
        //....不要在这里动虚函数表指针
        //memset(this,0,sizeof(C));

        m_c = 11; //初始化列表中基本类型变量m_c的赋值时机
        cout << "C::C()" << endl; //我们自己的代码

建议:尽量不要在构造函数和析构函数中调用虚函数。

猜你喜欢

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