【问题标题】:Object oriented programming , inheritance copy constructor面向对象编程,继承拷贝构造函数
【发布时间】:2010-01-15 09:35:07
【问题描述】:

假设我有一个基类“人”。我从基类“person”公开继承了一个类“student”。我还没有为基类和派生类编写复制构造函数。现在假设我在主程序中编写

main()
{
student sobj1("name", "computer science");
student sobj2=sobj1;
}

现在在第二行中,将调用默认编译器生成的学生的复制构造函数,但在执行之前,将调用基类的默认复制构造函数,这将创建一个匿名对象并对其进行初始化,然后控制权返回到副本学生的构造函数,它初始化对象的学生部分。
这是我们不编写复制构造函数的情况的演示
现在假设我们为这两个类编写了复制构造函数,那么我在编写时已经测试过了

student sobj2=sobj1;

发生的情况是,这一行调用了有效的学生的复制构造函数,但是在这种情况下不会调用基类的复制构造函数(将调用基类的默认构造函数)我的问题是为什么?

【问题讨论】:

  • 看起来这是一个 C++ 问题。您的意思是要包含 Java 标记吗?
  • 这肯定不是Java,第二行不会实例化任何类。
  • 也“公开继承”建议 C++
  • 它的 c++ ,很抱歉

标签: c++ oop


【解决方案1】:

vava 的规则几乎是正确的,这里有一个更明确的版本:

  • 如果不先构造基类子对象,就不能拥有派生类的实例:所有基类的 ctor 首先执行。 (Ctorconstructor 的简写。)
  • 如果不先构造该类的每个成员,就无法进入 ctor 的主体:所有成员的 ctor 都在 base 的 ctor 之后执行
  • 编译器生成的默认 ctor 使用默认 ctor 作为基数和成员。
  • 编译器生成的 cctor 会按成员进行复制:使用所有基和成员的复制 ctor。 (Cctor复制构造函数 的简写。)
  • 编译器生成的赋值运算符进行成员赋值:使用基数和成员的赋值运算符。 (赋值运算符也称为operator=op=。)
  • 当自己实现一个 ctor(任何 ctor,包括复制 ctor)时,任何没有初始化参数的基类或成员都将使用其默认 ctor(在 ctor 初始化程序中,冒号和之前的部分ctor 的函数体)。
  • 如果数据成员的默认 ctor 是微不足道的(或多或少“如果它是编译器生成的”)并且您没有在 ctor 初始化程序中指定该成员,那么该成员的值将是垃圾。
    • 这表明这些规则仍然过于简化;请参阅 C++ 标准中的 12.6.2/3-4 了解精致详细信息。
    • 这仅适用于具有普通默认 ctor 的数据成员。
    • 具有微不足道的默认 ctor 的基类始终是垃圾。

vava指定Person的copy ctor的例子是完全正确的:

struct Student : Person {
  Student(Student const& other) : Person(other) {}
};

最后一个项目符号的示例:

struct TrivialCtor { int n; };
struct A {
  TrivialCtor m;
  A() {}          // m.n is garbage
  A(int) : m() {} // m.n is 0

  friend ostream& operator<<(ostream& s, A const& v) {
    s << "m.n = " << v.m.n;
    return s;
  }
};

int main() {
  cout << "()   : " << A() << '\n';
  cout << "(int): " << A(42) << '\n';
  return 0;
}

【讨论】:

    【解决方案2】:

    我相信规则如下:

    1. 基类的构造函数始终应在派生类的构造函数之前调用。
    2. 您可以通过在初始化列表中显式调用来选择将调用哪一个基类构造函数。
    3. 如果不这样做,则会调用默认构造函数。
    4. 当类没有复制构造函数时,编译器会生成一个。它将为类的所有成员调用默认构造函数基类的复制构造函数,就像你的手写构造函数实际上应该那样。

    那么,就这样吧。除非你调用基类的复制构造函数,否则将使用默认的,但编译器足够聪明,可以在它自己生成的复制构造函数中实际调用它。

    万一你不知道怎么称呼它,有例子

    Student(Student const & p): Person(p) {
    }
    

    【讨论】:

      【解决方案3】:

      Roger 和 vava 已经回答了您的技术问题。

      但是,您现在可能没有意识到这一点,但您不希望支持从类的多态层次结构中复制对象。

      首先是因为复制实体没有意义。抄学生是什么意思?没有!

      其次,将一个学生复制到一个人然后再复制回一个学生时,您将不得不努力进行切片。而且您必须使用变通方法来支持分配 - 信封字母习语是最广为人知的。

      只需通过从诸如 boost::noncopyable 之类的类继承来禁止复制和赋值(对于纯 C++98/03 解决方案),并通过指针处理您的实体。如果出于某种奇怪的原因您确实需要复制实体,请查看依赖于受保护复制构造函数的常用 clone() 函数。

      【讨论】:

        猜你喜欢
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-09
        相关资源
        最近更新 更多