程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 對象構造與析構以及內存布局

C++ 對象構造與析構以及內存布局

編輯:C++入門知識

主要探討對象的構造順序與內存的布局,主要參考來源為《Exceptional C++ Style中文版》 文中第十四條 順序!順序!根據文中的代碼摘錄如下,代碼中添加了一些調試的信息。 [cpp]   #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';       }   };   class V1: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: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';       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 005F7F94 Constructor V1 005F7F94 Constructor B1 005F7F98 Constructor B2 005F7F9C Constructor V2 005F7F98 Constructor D1 005F7F88 Constructor B3 005F7F80 Constructor D2 005F7F80 Constructor M1 005F7F8C Constructor M2 005F7F90 Constructor X 005F7F80 -------------------------------------------- 0X5F7F80  Constructor B3 0X5F7F80  Constructor D2 0X5F7F80  Constructor X 0X5F7F88  Constructor D1 0X5F7F8C  Constructor M1 0X5F7F90  Constructor M2 0X5F7F94  Constructor B1 0X5F7F94  Constructor V1 0X5F7F98  Constructor B1 0X5F7F98  Constructor V2 0X5F7F9C  Constructor B2 -------------------------------------------- Destructor X 005F7F80 Destructor M2 005F7F90 Destructor M1 005F7F8C Destructor D2 005F7F80 Destructor B3 005F7F80 Destructor D1 005F7F88 Destructor V2 005F7F98 Destructor B2 005F7F9C Destructor B1 005F7F98 Destructor V1 005F7F94 Destructor B1 005F7F94   可以看出對象的構造順序和書中提示到的順序一致 類圖     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的繼承 。果然請看改造後的代碼。 [cpp]   #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還少構造了一次。哈哈~~果然很強大啊。。                                                                                

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved