簡體   English   中英

為什么隱式副本構造函數調用基類副本構造函數而未定義的副本構造函數調用?

[英]Why does the implicit copy constructor calls the base class copy constructor and the defined copy constructor doesn't?

考慮一個類層次結構,其中A是基類, BA派生A

如果未在B定義復制構造函數,則編譯器將合成一個。 調用時,此副本構造函數將調用基類副本構造函數 (即使用戶未提供,也將合成)。

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

輸出:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor

如果用戶在B定義了自己的副本構造函數,則在調用時,該副本構造函數將調用基類的默認構造函數 ,除非顯式存在對基類副本構造函數的調用(例如,在初始化列表中)。

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
    B(const B& rhs) {
        std::cout << "B::Copy constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

輸出:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor

我的問題是,為什么用戶定義的副本構造函數不將基類副本構造函數作為默認行為調用?

所有基本子構造函數都調用父默認構造函數。 這就是定義標准的方式。 正如您指出的那樣,如果您想要派生類B調用A的副本構造函數,則必須明確要求它

#include <iostream>

class A {
int a;
public:
A() {
    std::cout << "A::Default constructor" << std::endl;
}

A(const A& rhs) {
    std::cout << "A::Copy constructor" << std::endl;
}
};

class B : public A {
int b;
public:
B() {
    std::cout << "B::Default constructor" << std::endl;
}
B(const B& rhs):A(rhs) {
    std::cout << "B::Copy constructor" << std::endl;
}
};

int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}

之所以這樣,是因為編譯器無法為每個不同的構造函數知道應調用父對象的哪個構造函數,因此我們擁有默認的構造函數。對於所有其他構造函數,您必須明確聲明它們。

輸出:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor
B::Copy constructor

這就是定義隱式副本構造函數的方式(調用默認值是沒有意義的)。 一旦定義了任何構造函數(復制或其他形式),其通常的自動行為就是調用默認的父構造函數,因此對於一個特定的用戶定義的構造函數進行更改將是不一致的。

簡單的答案(可能是過時的)是因為您沒有告訴它。 由於您正在編寫派生的副本構造函數,因此可以完全控制它的行為。 無法指定對基類的調用,編譯器將通過調用基類的默認構造函數生成代碼以初始化基類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM