使用初始化列表(C + +)初始化父成员的受保护成员

是否可以使用子类的构造函数的初始化列表来初始化在父类中声明为 protected 的数据成员?我不能让它工作。我可以想办法解决,但如果不是迫不得已就好了。

一些示例代码:

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


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

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

非常感谢!

57654 次浏览

这是不可能的,在你描述的方式。您必须向基类添加一个构造函数(可能受到保护) ,以便将其转发。比如:

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


std::string something;
}


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

不行在派生类构造函数初始化列表中初始化父类的成员。它们是否受到保护,是否受到公众保护或者其他什么都不重要。

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

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

来自 C + + 0x 草案:

12.6.2初始化基地和成员

Mem-initializer-id 中的名称是 抬头望向天空 构造函数的类,如果没有找到 在那个范围内 包含构造函数的 定义。[注: 构造函数的类包含一个成员 与直接或间接投资者同名 类的虚拟基类,则 Mem-initializer-id 命名成员 或基类,并由单个 标识符引用类成员。 隐藏的 基类可以使用 限定名。ー结束注] 除非 Mem-initializer-id 将 构造函数的类,一个非静态数据 构造函数类的成员或 直接或虚拟的基础, Mem-initializer 格式不正确

注意: 强调我的。

也许你可以试试用“使用”这个关键词

class Parent
{


protected:
std::string something;
};


class Child : public Parent
{


private:
using Parent::something;
Child()
{
something="Hello, World!";
}
};

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

正如@dirkently 所说,不能在初始化列表中初始化父类成员的原因是因为此时尚未调用父类构造函数,所以这些字段不可用。

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

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