程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++類一定有構造函數嗎

C++類一定有構造函數嗎

編輯:C++入門知識

1:任何類如果沒有定義默認構造函數,就會合成出來?

2:合成出來的默認構造函數會明確設定類內每一個成員的值?

3:如何去證明呢?

如果你對1、2回答的都是不是,請跳過閱讀,以免浪費你的時間

對於問題1與2其實答案都是未必,C++標准是這樣寫的默認構造函數是由編譯器在需要的時候將其合成出來,這裡強調的是需要,而非必需,以程序示例:


[cpp] 
#include<iostream>  
#include<string>  
using namespace std; 
class A 

public: 
  char *ptr; 
  //string str;  
}; 
int main() 

    A b; 
    b.ptr=NULL; 
    return 0; 

#include<iostream>
#include<string>
using namespace std;
class A
{
public:
  char *ptr;
  //string str;
};
int main()
{
 A b;
 b.ptr=NULL;
 return 0;
}這個程序本身沒什麼好講的,能講的就是其匯編代碼,調試狀態下進入匯編代碼如下:


[cpp]
11:   { 
00401030   push        ebp 
00401031   mov         ebp,esp 
00401033   sub         esp,44h 
00401036   push        ebx 
00401037   push        esi 
00401038   push        edi 
00401039   lea         edi,[ebp-44h] 
0040103C   mov         ecx,11h 
00401041   mov         eax,0CCCCCCCCh 
00401046   rep stos    dword ptr [edi] 
12:       A b; 
13:       b.ptr=NULL; 
00401048   mov         dword ptr [ebp-4],0 
14:       return 0; 
0040104F   xor         eax,eax 
15:   } 

11:   {
00401030   push        ebp
00401031   mov         ebp,esp
00401033   sub         esp,44h
00401036   push        ebx
00401037   push        esi
00401038   push        edi
00401039   lea         edi,[ebp-44h]
0040103C   mov         ecx,11h
00401041   mov         eax,0CCCCCCCCh
00401046   rep stos    dword ptr [edi]
12:       A b;
13:       b.ptr=NULL;
00401048   mov         dword ptr [ebp-4],0
14:       return 0;
0040104F   xor         eax,eax
15:   }
你能找到構造函數調用的地方嗎即A::A(),:),找不到吧,因為壓根就沒有構造函數,這個類就相當於一個整形變量(存儲上相似,用法上不同),其空間是堆棧ebp+4這裡的4個字節

將程序注釋中的

[cpp] 
//string str; 

 //string str;
去掉,再次進入匯編看看,代碼如下:
[html]
10:   int main() 
11:   { 
00401070   push        ebp 
00401071   mov         ebp,esp 
00401073   sub         esp,58h 
00401076   push        ebx 
00401077   push        esi 
00401078   push        edi 
00401079   lea         edi,[ebp-58h] 
0040107C   mov         ecx,16h 
00401081   mov         eax,0CCCCCCCCh 
00401086   rep stos    dword ptr [edi] 
12:       A b; 
00401088   lea         ecx,[ebp-14h] 
0040108B   call        @ILT+15(A::A) (00401014) 
13:       b.ptr=NULL; 
00401090   mov         dword ptr [ebp-14h],0 
14:       return 0; 
00401097   mov         dword ptr [ebp-18h],0 
0040109E   lea         ecx,[ebp-14h] 
004010A1   call        @ILT+30(A::~A) (00401023) 
004010A6   mov         eax,dword ptr [ebp-18h] 
15:   } 

10:   int main()
11:   {
00401070   push        ebp
00401071   mov         ebp,esp
00401073   sub         esp,58h
00401076   push        ebx
00401077   push        esi
00401078   push        edi
00401079   lea         edi,[ebp-58h]
0040107C   mov         ecx,16h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]
12:       A b;
00401088   lea         ecx,[ebp-14h]
0040108B   call        @ILT+15(A::A) (00401014)
13:       b.ptr=NULL;
00401090   mov         dword ptr [ebp-14h],0
14:       return 0;
00401097   mov         dword ptr [ebp-18h],0
0040109E   lea         ecx,[ebp-14h]
004010A1   call        @ILT+30(A::~A) (00401023)
004010A6   mov         eax,dword ptr [ebp-18h]
15:   }
看看,我們的構造函數出現了吧A:A() :),為什麼會出現呢?
因為類裡面有一個類叫string,我們跟蹤發現string類定義在include/xstring裡,其形式如下:


[cpp] 
typedef basic_string<char, char_traits<char>, allocator<char> > 
    string; 

typedef basic_string<char, char_traits<char>, allocator<char> >
 string;這是一個模板類,屬於STL范疇,不信你看看SGI STL源碼,在機會再講,繼教跟蹤,你會發現basic_string有一系列的構造函數,如下:


[html] 
explicit basic_string(const _A& _Al = _A()) 
    : allocator(_Al) {_Tidy(); } 
basic_string(const _Myt& _X) 
    : allocator(_X.allocator) 
    {_Tidy(), assign(_X, 0, npos); } 
basic_string(const _Myt& _X, size_type _P, size_type _M, 
    const _A& _Al = _A()) 
    : allocator(_Al) {_Tidy(), assign(_X, _P, _M); } 
basic_string(const _E *_S, size_type _N, 
    const _A& _Al = _A()) 
    : allocator(_Al) {_Tidy(), assign(_S, _N); } 
basic_string(const _E *_S, const _A& _Al = _A()) 
    : allocator(_Al) {_Tidy(), assign(_S); } 
basic_string(size_type _N, _E _C, const _A& _Al = _A()) 
    : allocator(_Al) {_Tidy(), assign(_N, _C); } 

 explicit basic_string(const _A& _Al = _A())
  : allocator(_Al) {_Tidy(); }
 basic_string(const _Myt& _X)
  : allocator(_X.allocator)
  {_Tidy(), assign(_X, 0, npos); }
 basic_string(const _Myt& _X, size_type _P, size_type _M,
  const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_X, _P, _M); }
 basic_string(const _E *_S, size_type _N,
  const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_S, _N); }
 basic_string(const _E *_S, const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_S); }
 basic_string(size_type _N, _E _C, const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_N, _C); }其實重要的是第一個構造函數,因為此處調用就是它,給basic_string分配一個內存分配管理器:)

明白了吧,此處有是因為類裡面有一個string類的對象,別人屬於你,別人有自已的構造函數,需要為其賦一個初始值,你總不能不讓吧,於是編譯器就合成一個默認的構造函數,調用string裡的構造函數,為string對像置一個初始狀態

構造函數的確是不一定會有的,而且類裡的一些內置類型默認構造函數也不會給其設定一個默認值的,不信你再看看匯編,哪裡有對ptr的賦值:)

有四種情況編譯器會為合成默認構造函數

1:含有默認默認/構造函數的成員類對象

2:帶有默認/構造函數的基類對象

3: 含有虛函數的類

4:繼承虛基類的類

 

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