提问人:And.Re 提问时间:11/10/2023 最后编辑:And.Re 更新时间:11/10/2023 访问量:77
受保护类的继承
Inheritance of protected class
问:
我对这段代码有疑问(这是一个测试问题,所以我不需要更改):
class X {
protected:
int v;
};
class Y : protected X {
public:
Y() : v(0) {}
};
int main()
{
Y *y = new Y();
cout << y->v;
delete y;
return 0;
}
我很确定这很好,因为 X 的 v 成员可以从 Y 访问,因为 Y 是受保护类的子类,该类具有受保护成员 (v),但我有一个编译错误。 有人可以帮我理解吗?谢谢!
答:
我很确定这很好,因为 X 的 v 成员可以从 Y 访问......
Y
有权访问 。在代码中,您尝试从 访问它。v
main
你误解了声明成员的含义。它不是一种将基类中无法从外部访问的内容转换为派生类中每个人都可以访问的内容的机制。它只为派生类提供访问权限:protected
class X {
public:
X(int v) : v(v) {}
protected:
int v;
};
class Y : public X {
public:
Y() : X(0) { // Base class initializes its members
std::cout << v; // OK
}
};
此外,你似乎将继承与成为成员混为一谈,我把它从上面删除了。它并没有改变无法从外部访问的事实,我认为它超出了问题的范围。您应该同时阅读以下两种内容:受保护的成员和受保护的继承。protected
protected
v
PS:默认情况下不要使用手动动态内存分配。你的应该是main
Y y;
cout << y.v;
它会有完全相同的问题。如果确实需要动态分配某些内容,请使用智能指针来管理生存期。
至少有两个问题。
第一个是类定义
class X {
protected:
int v;
};
class Y : protected X {
public:
Y() : v(0) {}
};
是 ijll 形成的。来自 C++17 标准( 15.6.2 初始化基和成员):
2 在 mem-initializer-id 中,查找初始非限定标识符 在构造函数类的范围内,如果找不到 作用域,则在包含构造函数的 定义。[ 注意:如果构造函数的类包含一个成员 与类的直接基类或虚拟基类同名,一个 mem-initializer-id 命名成员或基类,由 单个标识符是指类成员。一个 mem-initializer-id 用于 可以使用限定名指定隐藏的基类。— 完 note ] 除非 mem-initializer-id 命名构造函数的类, 构造函数类的非静态数据成员,或者直接或 该类的虚拟基,mem-initializer 格式不正确。
也就是说,在类的 ctor 初始化中,您不能将基类的非静态成员用作初始化成员:v
X
Y
Y() : v(0) {}
^^^^
第二个问题是,由于数据成员在派生类中受到保护,因此您不能像现在这样直接在类外部访问它v
Y
cout << y->v;
将数据成员设为公共,或创建一个公共成员函数,该函数将返回数据成员的值或对数据成员的常量引用。v
评论
cout << y->v;
只能访问类成员。public
Y
有访问权限v
Y
main()
main()
protected
cout << y->v