145

是否可以使用子类的构造函数的初始化列表来初始化在父类中声明为受保护的数据成员?我无法让它工作。我可以解决它,但如果我不必这样做会很好。

一些示例代码:

class Parent
{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child() : something("Hello, World!")
    {
    }
};

当我尝试这个时,编译器告诉我:“类'Child'没有任何名为'something'的字段”。这样的事情可能吗?如果是这样,语法是什么?

非常感谢!

4

5 回答 5

139

按照你描述的方式是不可能的。您必须向基类添加一个构造函数(可能受到保护)才能转发它。就像是:

class Parent
{
protected:
    Parent( const std::string& something ) : something( something )
    {}

    std::string something;
}

class Child : public Parent
{
private:
    Child() : Parent("Hello, World!")
    {
    }
}
于 2010-02-18T17:33:02.580 回答
72

当编译器遇到初始化列表时,派生类对象尚未形成。直到那时还没有调用基类构造函数。只有在基类构造函数被调用之后,something才会出现。因此问题。当您不显式调用基类构造函数时,编译器会为您执行此操作(通过为基类生成适当的普通构造函数)。这会导致something成员被默认初始化。

来自 C++0x 草案:

12.6.2 初始化基和成员

2 mem-initializer-id 中的名称在构造函数类的范围内查找,如果在该范围内未找到,则在包含构造函数定义的范围内查找。[注:如果构造函数的类包含与该类的直接或虚拟基类同名的成员,则命名该成员或基类并由单个标识符组成的mem-initializer-id指的是类成员。可以使用限定名称指定隐藏基类的 meminitializer-id。—end note ]除非 mem-initializer-id 命名构造函数的类、构造函数类的非静态数据成员或该类的直接或虚拟基类,否则 mem-initializer 格式错误。

注意:强调我的。

于 2010-02-18T17:40:10.330 回答
18

不能在派生类构造函数初始化列表中初始化父类的成员它们是否受到保护、公开或其他任何东西都没有关系。

在您的示例中,成员somethingParent类的成员,这意味着它只能在Parent类的构造函数初始化程序列表中进行初始化。

于 2010-02-18T17:35:16.343 回答
0

正如@philsquared 所说,您不能从孩子的成员初始化列表中初始化父类的成员,但您可以添加一个父类构造函数,并从孩子的成员初始化列表中调用此构造函数。

而且正如@dirkgently 所说,之所以不能在初始化列表中初始化父类的成员,是因为此时还没有调用父类的构造函数,所以这些字段不可用。

对于后人,我还想指出,如果您不想为父类编写构造函数,则可以在构造函数的主体中初始化受保护的成员:

class Child : public Parent
{
private:
    Child() {
        something = "Hello, World!";
    }
};
于 2022-01-19T13:50:09.483 回答
-4

也许您可以使用关键字“使用”以这种方式尝试

class Parent
{

protected:
std::string something;
};

class Child : public Parent
{

private:
using Parent::something;
Child()
{
    something="Hello, World!";
}
};
于 2017-04-27T20:34:21.860 回答