面向对象编程,继承,复制构造函数

4
假设我有一个基类Person,并且我从基类Person公开继承了一个类Teacher。 现在,在主函数中,我写了以下内容:
// name will be passed to the base class constructor and 17
// is for derived class constructor.
Teacher object(“name”,17) ;
Teacher object1=object; //call to copy constructor

现在我还没有为这两个类编写复制构造函数,当然会调用默认的复制构造函数。Person类的默认复制构造函数将首先调用基类的复制构造函数。
现在的问题是,假设我只为基类编写复制构造函数,那么派生类的默认复制构造函数将调用我编写的复制构造函数。
现在假设我为这两个类都编写了复制构造函数。现在派生类(即Teacher)的复制构造函数将调用基类的默认构造函数,但不会调用复制构造函数,为什么?
难道只有派生类的默认复制构造函数才能自动调用基类的复制构造函数吗?

并不存在所谓的“默认复制构造函数”。但是编译器生成的复制构造函数会调用基类的复制构造函数。 - Martin York
谢谢,现在我明白了重点。 - Zia ur Rahman
3个回答

8

您需要显式调用基类的复制构造函数:

Teacher(const Teacher& other) 
    : Person(other) // <--- call Person's copy constructor.
    , num_(other.num_)
{
}

否则将调用Person的默认构造函数。
我似乎没有完全理解问题,所以我会说出我认为相关的一切,希望这能帮助提问者。
所有用户定义的构造函数默认情况下都会调用其基类的默认构造函数(除非它们显式地调用不同的构造函数),无论基类的默认构造函数是用户定义的还是编译器生成的。
当编译器生成复制构造函数时,它将调用基类的复制构造函数。
编译器定义的构造函数并不特殊,它们可以被显式调用:
class Base {
    int num_
public:
    Base(int n) : num_(n) { }
    // copy constructor defined by compiler
};

class Derived : public Base {
    float flt_;
public:
    Derived(float f, int n) : Base(n), flt_(f) { }
    // Copy constructor
    Derived(const Derived& other)
        : Base(other) // OK to explicitly call compiler generated copy constructor
        , flt_(other.flt_)
    {
    }
};

更多详情请查看维基百科文章


是的,我知道,我必须显式调用它,但这不是我的问题,我的问题是“仅派生类的默认复制构造函数可以调用基类的复制构造函数(默认或用户编写)”? - Zia ur Rahman
1
我不理解你的问题。 - Motti
编译器生成的复制构造函数版本并不特殊。编译器生成的复制构造函数将调用基类的复制构造函数(无论是用户编写的还是编译器生成的),然后调用每个成员的复制构造函数(无论它们是用户编写的还是编译器生成的复制构造函数)。 - Martin York
1
注意:不存在所谓的“默认复制构造函数”。您似乎混淆了“默认构造函数”这个术语,它是在没有提供参数时调用的构造函数。编译器生成的方法有“复制构造函数”、“赋值运算符”、“默认构造函数”和“析构函数”。 - Martin York
这意味着只有派生类的编译器生成的复制构造函数可以自动调用基类的复制构造函数,用户编写的派生类复制构造函数不能自动调用基类的复制构造函数,我说得对吗? - Zia ur Rahman
显示剩余2条评论

1
class Base {
    int num_
public:
    Base(int n) : num_(n) { }
    // copy constructor defined by compiler
};

class Derived : public Base {
    float flt_;
public:
    Derived(float f, int n) : Base(n), flt_(f) { }
    // Copy constructor
    Derived(const Derived& other)
        : Base(other) // OK to explicitly call compiler generated copy constructor
        , flt_(other.flt_)
    {
    }
};

1

如果您没有指定复制构造函数,编译器会自动生成一个。这个构造函数是以调用基类的复制构造函数的方式生成的。

如果您自己实现了复制构造函数,您还需要指定应该使用哪个基类构造函数(请参见Motti的答案)。如果您没有指定任何内容,则使用默认构造函数(这就是为什么它被称为“默认构造函数”:当没有显式指定构造函数时使用它)。

因此,编译器会自动生成一个合理的复制构造函数,但如果您想要特殊的东西,就不会有进一步的魔法,您必须自己指定该构造函数的确切样子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接