c++ 保护类的继承

zpf6vheq  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(70)

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

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

2ul0zpep

2ul0zpep1#

我很确定它是好的,因为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;


如果你确实需要动态分配一些东西,使用智能指针来管理生存期。

rdrgkggo

rdrgkggo2#

至少有两个问题。
第一个是类的定义

class X {
    protected:
    int v;
};

class Y : protected X {
public:
    Y() : v(0) {}
    
};

字符串
来自C++17标准(15.6.2初始化基和成员):
2在mem-initializer-id中,在构造函数类的作用域中查找初始的非限定标识符,如果在该作用域中找不到,则在包含构造函数定义的作用域中查找。[注意:如果构造函数的类包含与该类的直接基类或虚基类同名的成员,命名成员或基类并由单个标识符组成的mem-initializer-id引用类成员。隐藏基类的mem-initializer-id可以使用限定名指定。- end note ]除非mem-initializer-id命名构造函数'的类,构造函数类的非静态数据成员,或者该类的直接或虚基类,则mem-initializer是格式错误的
也就是说,你不能使用基类X的非静态成员v作为类Y的ctor初始化中的初始化成员:

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


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

cout << y->v;


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

相关问题