受保护类的继承

Inheritance of protected class

提问人:And.Re 提问时间:11/10/2023 最后编辑:And.Re 更新时间:11/10/2023 访问量:77

问:

我对这段代码有疑问(这是一个测试问题,所以我不需要更改):

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),但我有一个编译错误。 有人可以帮我理解吗?谢谢!

C++ 继承 保护

评论

4赞 Richard Critten 11/10/2023
"。但我有一个编译错误......“任何错误都应以格式化文本的形式出现在问题中。
1赞 πάντα ῥεῖ 11/10/2023
cout << y->v;只能访问类成员。public
0赞 463035818_is_not_an_ai 11/10/2023
Y有访问权限v
5赞 HolyBlackCat 11/10/2023
您不是从 访问成员,而是从 访问成员。Ymain()
0赞 Peter 11/10/2023
中的语句不能直接访问类的成员。 试图完全做到这一点,所以没有编译。main()protectedcout << y->v

答:

3赞 463035818_is_not_an_ai 11/10/2023 #1

我很确定这很好,因为 X 的 v 成员可以从 Y 访问......

Y有权访问 。在代码中,您尝试从 访问它。vmain

你误解了声明成员的含义。它不是一种将基类中无法从外部访问的内容转换为派生类中每个人都可以访问的内容的机制。它只为派生类提供访问权限: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
    }    
};
    

此外,你似乎将继承与成为成员混为一谈,我把它从上面删除了。它并没有改变无法从外部访问的事实,我认为它超出了问题的范围。您应该同时阅读以下两种内容:受保护的成员和受保护的继承。protectedprotectedv


PS:默认情况下不要使用手动动态内存分配。你的应该是main

Y y;
cout << y.v;

它会有完全相同的问题。如果确实需要动态分配某些内容,请使用智能指针来管理生存期。

1赞 Vlad from Moscow 11/10/2023 #2

至少有两个问题。

第一个是类定义

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 初始化中,您不能将基类的非静态成员用作初始化成员:vXY

Y() : v(0) {}
      ^^^^

第二个问题是,由于数据成员在派生类中受到保护,因此您不能像现在这样直接在类外部访问它vY

cout << y->v;

将数据成员设为公共,或创建一个公共成员函数,该函数将返回数据成员的值或对数据成员的常量引用。v