繁体   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