使用派生类构造函数填充基类受保护成员的C++代码

3
我有一个类似这样的东西:
Class Base
{
  public:
    Base();
  protected:
    someType myObject;
}

Class Child:public someNamespace::Base
{
   //constructor
   Child(someType x):myObject(x){}
}

类Child和Base位于两个不同的命名空间中... 编译器报错,说我的Child类没有名为myObject的字段。

有人知道原因吗?是因为从Child构造函数填充Base成员是非法的吗?

谢谢

2个回答

4

你不能像那样初始化继承的成员。相反,你可以给基类一个构造函数来初始化该成员,然后派生类可以调用该构造函数。

class Base
{
  public:
    Base(someType x) : myObject{x} {}
  protected:
    someType myObject;
}

class Child : public Base
{
  public:
    //constructor
    Child(someType x) : Base(x) {}
}

通常情况下,一个类应该负责初始化它自己的成员。

好的,明白了。我会试一试的。谢谢 - Telenoobies
1
@Telenoobies:如果myObject只在基类中访问,你也应该将其设置为private - Christian Hackl
2
你也可以将基础构造函数设置为protected,这样只有派生类才能调用它。 - Nick Strupat
你是否将Child构造函数更改为Child(someType x) : someNamespace::Base(x) {} - Cory Kramer
是的...基类可以有两个构造函数,对吧? 一个是空的,另一个带有一些类型参数。它们看起来像这样:类 基类 { public: Base::Base(); Base::Base(SomeType x); } - Telenoobies
搞定了!我必须在子类的构造函数中分配基类成员,而不是在子类的初始化列表中。感谢大家的帮助。 - Telenoobies

2
这里的问题在于您在初始化列表中初始化了继承的myObject。当派生类的对象被创建时,在进入派生类构造函数体之前,基类的构造函数会被调用(默认情况下,如果基类具有默认或无参数构造函数,则会调用它,否则必须在初始化列表中显式调用构造函数)。
所以,当您执行:: Class Child:public someNamespace::Base时,尚未调用基类的构造函数,这就是为什么编译器会抱怨:: Child class does not have a field called myObject,即实际上您正在尝试为尚未声明和定义的东西分配值!它将在Base类的构造函数进入执行后定义。
因此,您的Child类构造函数将如下所示:
   Child(someType x) {
      myObject = x;
   }

可运行的 ideone 链接 :: http://ideone.com/70kcdC

我在前面的回答中发现了这一点的缺失,所以我认为这可能会帮助到您!


好的,你说:“当你这样做时::Class Child:public someNamespace::Base,你的基类构造函数还没有被调用。”解决这个问题的方法是在Child的构造函数中进行赋值,而不是在Child的初始化列表中进行赋值? - Telenoobies
@Telenoobies:是的,因为当您进入Child的构造函数体时,您的Base类成员已经被创建了,因为Base类构造函数已经完成了执行,并且myObject已经被定义。当您在初始化列表中进行初始化时,基类对象尚未创建,这就是为什么错误显示“Child类没有名为myObject的字段”的原因。 - user007

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