C++ 对象构造与析构以及内存布局
主要探讨对象的构造顺序与内存的布局,主要参考来源为《Exceptional C++ Style中文版》
文中第十四条 顺序!顺序!根据文中的代码摘录如下,代码中添加了一些调试的信息。
1.首先构造虚基类子对象
2.其次构造非虚基类子对象.
3.构造成员本身
4.构造对象本身
以上同等级的构造顺序遵循从左到右的申明顺序。
但是问题出现了
问题1:这个对象X的对象内存分布是这个样子的。看上去地址是倒着分配的。首地址相近的并不是最先分配的那个对象。是个问题。。。大家可以考虑一下到底怎么分布啊???我的编译平台是VS2010
问题2:假如说类B1中含有某个方法,那么X对象调用的是哪块内存上的函数呢??
我猜是左边的那个。废话少说写测试代码。
改造一下后编译竟然发现编译问题
1>e:\opensource\exceptional c++ style\example_014class\example_014class.cpp(191): error C2385: ambiguous access of 'fun'
1> could be the 'fun' in base 'B1'
1> or could be the 'fun' in base 'B1'看样子编译器他决定不了X对象将会调用内存中哪块B1的函数。
是否就没有办法了呢?
想起对象模型的那本曾提到这种情况下使用 virtual的继承 。果然请看改造后的代码。
#include <map>struct classcomp { bool operator() (const __int64& lhs, const __int64& rhs) const {return lhs<rhs;}};std::multimap<__int64,std::string,classcomp> m_Construtor;class B1{ public: B1() { std::cout<<"Constructor B1 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor B1 ")); } virtual ~B1() { std::cout<<"Destructor B1 "<<this<<'\n'; } void fun() { std::cout<<"fun B1 "<<this<<'\n'; }};class V1:virtual public B1{public: V1() { std::cout<<"Constructor V1 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor V1 ")); } virtual ~V1() { std::cout<<"Destructor V1 "<<this<<'\n'; }};class D1:virtual public V1{public: D1() { std::cout<<"Constructor D1 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor D1 ")); } virtual ~D1() { std::cout<<"Destructor D1 "<<this<<'\n'; }};class B2{public: B2() { std::cout<<"Constructor B2 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor B2 ")); } virtual ~B2() { std::cout<<"Destructor B2 "<<this<<'\n'; }};class B3{public: B3() { std::cout<<"Constructor B3 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor B3 ")); } virtual ~B3() { std::cout<<"Destructor B3 "<<this<<'\n'; }};class V2:virtual public B1,public B2{public: V2() { std::cout<<"Constructor V2 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor V2 ")); } virtual ~V2() { std::cout<<"Destructor V2 "<<this<<'\n'; }};class D2:public B3,virtual public V2{public: D2() { std::cout<<"Constructor D2 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor D2 ")); } virtual ~D2() { std::cout<<"Destructor D2 "<<this<<'\n'; }};class M1{public: M1() { std::cout<<"Constructor M1 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor M1 ")); } virtual ~M1() { std::cout<<"Destructor M1 "<<this<<'\n'; }};class M2{public: M2() { std::cout<<"Constructor M2 "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor M2 ")); } virtual ~M2() { std::cout<<"Destructor M2 "<<this<<'\n'; }};class X: public D1, public D2{public: X() { std::cout<<"Constructor X "<<this<<'\n'; m_Construtor.insert(std::pair<__int64,std::string>((__int64)this,"Constructor X ")); } virtual ~X() { std::cout<<"Destructor X "<<this<<'\n'; }private: M1 _m1; M2 _m2;};int _tmain(int argc, _TCHAR* argv[]){ //B b; int i; X *pX = new X; std::cout<<"--------------------------------------------"<<'\n'; pX->fun(); std::cout<<"--------------------------------------------"<<'\n'; cout.setf(ios::showbase | ios::uppercase); //设置基指示符输出和数值中的字母大写输出 std::multimap<__int64,std::string,classcomp> ::iterator iter; for (iter = m_Construtor.begin();iter != m_Construtor.end();++iter)//遍历 { cout<<std::hex<<(*iter).first<<" "<<(*iter).second<<endl; } std::cout<<"--------------------------------------------"<<'\n'; delete pX; pX = NULL; std::cin>>i;return 0;}运行结果:Constructor B1 00127F94
Constructor V1 00127F98
Constructor B2 00127F9C
Constructor V2 00127F9C
Constructor D1 00127F88
Constructor B3 00127F80
Constructor D2 00127F80
Constructor M1 00127F8C
Constructor M2 00127F90
Constructor X 00127F80
--------------------------------------------
fun B1 00127F94
--------------------------------------------
0X127F80 Constructor B3
0X127F80 Constructor D2
0X127F80 Constructor X
0X127F88 Constructor D1
0X127F8C Constructor M1
0X127F90 Constructor M2
0X127F94 Constructor B1
0X127F98 Constructor V1
0X127F9C Constructor B2
0X127F9C Constructor V2
--------------------------------------------
Destructor X 00127F80
Destructor M2 00127F90
Destructor M1 00127F8C
Destructor D2 00127F80
Destructor B3 00127F80
Destructor D1 00127F88
Destructor V2 00127F9C
Destructor B2 00127F9C
Destructor V1 00127F98
Destructor B1 00127F94
发现类B1还少构造了一次。哈哈~~果然很强大啊。。