簡體   English   中英

派生類中默認(隱式)副本構造函數的C ++行為

[英]C++ behavior of a default(implicit) copy constructor in a derived class

我對默認副本構造函數的行為有疑問。 例如,如下所示的類:

class A{
public:
    A(){}
    A(const A& a){}
    ~A(){}
    void foo(){}
};
class B:public A{
    public:
    B(){}
    B(const B& b){}
    B& operator=(const B& b){return *this;}
    ~B(){}
    virtual void foo(){}
};
class C:public B{
public:
    C(){}
    C& operator=(const C& c){a_=c.a_; return *this;}
    ~C(){}
    void foo(){}
protected:
    A a_;
};

如果我將創建一個新的類C的對象,例如:

C* c1 = new C();

步驟將是:

  1. 通過顯式A()創建A
  2. 通過顯式B()創建B
  3. 通過顯式A()創建A(類C中的受保護成員a_)
  4. 通過顯式C()創建C

如果我要像這樣初始化C類的新對象:

    C c2(*c1);

它會調用C的默認副本構造函數。據我所知,這些步驟將是:

  1. 調用類C的隱式副本構造函數
  2. 它調用顯式的A()。 為什么不使用A(const A&a)?
  3. 顯式B(const B&b)。 為什么不像基類A那樣通過B()?
  4. 最后,它將為類C a_中的受保護成員調用顯式A(const A&a)。 這次有什么區別? 為什么現在是復制者
  5. 顯式C&運算符=(const C&c)被調用。 為什么調用operator =? 據我所知,當我們初始化一個新對象而不是賦值運算符時,將使用復制構造函數
  6. A(const A&a)被調用為a_ = c.a_(在C&operator =中)

默認副本構造函數的行為如何? 它有什么規則?

我嘗試在Internet上搜索默認副本構造函數的實現,但沒有找到解釋此行為的內容。 有人可以建議一些有關此問題的信息嗎?

當您有派生類復制構造函數時,例如...

C(const C& c) {...}

您可能會認為這會自動調用A和B的復制控制器,但不會。 隱式行為就像您已經寫過...

C(const C& c) : B() {...}

...然后B的B()做...

B() : A() {...}

如果要在基類中調用復制ctor,則需要顯式指定這種行為,例如...

C(const C& c) : B(c) {...}

隱式生成的復制控制器已經為您完成了此操作。

據您所見,在您所處的情況下, operator=被調用的事實並非如此 我不知道你為什么會這樣。

編譯運行,檢查代碼中的注釋,將會更加清晰:

#include <iostream>

class A{
public:
    A()
    {

    }
    A(const A& a)
    {
        std::cout << "Copy constructor FOR A is being called" << std::endl;
    }
    virtual ~A(){}
    void foo(){}
};

class B : public A
{
public:
    B()
    {

    }
    B(const B& b)
    {
        std::cout << "Copy constructor FOR B is being called" << std::endl;
    }
    B& operator=(const B& b){return *this;}
    virtual ~B()
    {

    }
    virtual void foo(){}
};

class C : public B
{
public:
    C()
    {

    }

    //if you remove this copy constructor, instead of only C being called, both A and B's copy constructor will be called
    C(const C& c)
    {
        std::cout << "Copy constructor FOR C is being called" << std::endl;
    }

    C& operator()(const C& c)
    {
        std::cout << "Operator is being called" << std::endl;
        a_=c.a_;
        return *this;
    }

    ~C()
    {

    }
    void foo()
    {

    }
protected:
    A a_;
};

int main()
{
    C* c = new C();
    C c2(*c); //copy constructor C will be called since we declared one, otherwise both A's and B's copy constructor would be called
    c2(c2); //here the operator() will be called but not above, changed that one to operator() since operator= didn't make sense
    delete c;

    std::cin.get();
    return 0;
}

暫無
暫無

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

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