派生类

时间:2015-07-25 23:27:43

标签: c++

我对默认复制构造函数的行为有疑问。例如,像这样的类:

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()
  2. 创建A.
  3. 通过显式B()
  4. 创建B.
  5. 通过显式A()(C类中的受保护成员a_)创建A
  6. 通过显式C()
  7. 创建C.

    如果我将初始化C类的新对象,如:

        C c2(*c1);
    

    它将调用C的默认复制构造。据我所知,步骤将是:

    1. 调用C类隐式复制构造函数
    2. 它调用显式的A()。 为什么不是A(const A& a)?
    3. 显式B(const B& b)。 为什么B()不像基类A?
    4. 最终会在C类a_中为受保护成员调用显式A(const A& a)。 这次有什么不同?为什么现在是副本c' tor
    5. 明确的C& operator =(const C& c)被调用。 为什么调用operator =?据我所知,当我们初始化一个新对象而不是赋值运算符
    6. 时,会使用复制构造函数
    7. a(const A& a)被调用a_ = c.a_(在C& operator =的主体中)
    8. 默认复制构造函数的行为如何?它有什么规则?

      我试图在互联网上搜索默认复制构造函数的实现,但我没有找到解释这种行为的东西。任何人都可以建议阅读有关此问题的内容吗?

2 个答案:

答案 0 :(得分:2)

如果有派生类复制构造函数,例如......

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

你可能会认为这会自动调用A和B的副本,但事实并非如此。隐含的行为就好像你写了......

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

......然后B的B()确实......

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

如果你想要复制ctors到你的基类,你需要明确指定这样的行为...

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

隐式生成的副本已经为您完成此操作。

至于您的观察operator=在您的情况下被调用it isn't。我不知道你为什么这么认为。

答案 1 :(得分:0)

编译并运行,检查代码中的注释,将更加清晰:

#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;
}