1. 程式人生 > >C++編譯器自動生成拷貝建構函式的情況

C++編譯器自動生成拷貝建構函式的情況

編譯器在下面幾種情況下會給程式設計師沒有提供拷貝建構函式的類自動生成拷貝建構函式

1.類中有虛擬函式

當這個類中有虛擬函式的時候,意味著這個類的物件中一定包含了指向其虛擬函式表的指標

試想,如果講該類的派生類的物件作為該類的初始化物件,即

B繼承A

class A

{

private:

    int m_a;

public:

    virtual void ShowVal();
}

 

void A::ShowVal()

{

    printf("%d", m_a);
}

 

Class B

{

private:

    int m_b;

public:

    void ShowVal();
}

 

void B::ShowVal()

{

      printf("%d", m_a);
}

 

int main()

{

    B b;

    A a = b;   // 此處應該呼叫A類的拷貝建構函式
}

在main中A a = b;時,如果程式設計師沒有提供拷貝建構函式,而編譯器也不提供,那麼就會按照簡單的位拷貝進行拷貝,即將b物件中a子物件的部分按位拷貝給a物件,這是就會出現一個問題,b物件中包含的vbpt指向的時B類的虛擬函式表,而不是A類的。如果這樣直接位拷貝的時候,當呼叫a.ShowVal函式,執行的時B類的ShowVal,就不正確了。

因此,這裡編譯器判斷A類在拷貝構造的時候並沒有顯現出位拷貝的特徵,不能只是用位拷貝,因此編譯器會為A類合成一個拷貝建構函式,如下

A::A(A& a)

{

    this->vptr = A類的虛擬函式表的地址;
}

即編譯器必須查收生成一個拷貝建構函式用來重新設定vptr的值。

在這裡插一句,如果程式設計師提供了拷貝建構函式的話,編譯器會不會做什麼動作?

答案時當然會,因為程式設計師提供的拷貝建構函式中也不會去做重新設定vptr的動作,這裡當然會由編譯器代勞了,編譯器會在程式設計師提供的拷貝建構函式中