【问题标题】:How can I access base class's protected members through derived class? [duplicate]如何通过派生类访问基类的受保护成员? [复制]
【发布时间】:2019-08-27 05:00:40
【问题描述】:

我正在尝试几个关于继承的程序,结果发现以下导致错误,但我真的不知道原因。

#include <iostream>

using namespace std;

class Base {
protected:
    int x = 0;
};

class Derived: public Base {

    // OK: access protected member via this
    void g() { cout<<x; } 

    // OK: access protected member of other Derived
    void h(Derived& d) { cout<<d.x; } 

    // FAIL: access Base class's protected member, why?
    void f(Base& b) { cout<<b.x; } 
};

int main() {}

我希望派生类可以访问基类的公共或受保护数据成员和成员函数。

但是它并没有像我想的那样起作用,有人可以帮我阐明我的概念吗?

【问题讨论】:

  • “没用”怎么办?它编译了吗?如果没有,错误应该在您的问题中。
  • 真的很抱歉描述不清楚,程序无法编译,我也不清楚背后的原理。
  • Accessing protected members in a derived class 可能重复 - 这是完全相同的问题。
  • 它只是被 [class.protected] 中的标准明确禁止,并且有一个与您相同的示例。
  • @SeanTsai 没问题 - 我只是稍微重新排序了您的代码,以便更容易看出哪种情况失败。

标签: c++


【解决方案1】:
void f(Base& b) {cout<<b.x;}

在这里,您尝试访问不同类的受保护成员。您是否也共享相同的基类并不重要。 (仍在寻找来源)

void g() {cout<<x;}

在此示例中,您正在访问自己的私有成员。 (基类的受保护成员在派生类中被继承和保护)

void h(Derived& d) {cout<<d.x;}

在这里,您正在访问同一类的私有成员。但有关此内容的更多信息,请查看此帖子:Access private elements of object of same class

【讨论】:

    【解决方案2】:

    没有比你已经发现的更多的了。派生实例可以访问它们的受保护成员和其他派生实例的成员,但不能访问基类实例的成员。为什么?因为这就是protected 的定义方式。

    如需了解更多详情,请联系cppreference(强调我的):

    类Base的受保护成员只能被访问

    1) 基地的成员和朋友

    2) 由会员和朋友(直到 从 Base 派生的任何类的 C++17),但仅在对 从 Base 派生的类型的对象(包括 this)

    【讨论】:

      【解决方案3】:

      来自this documentation

      类 Base 的受保护成员只能被访问

      1. 基地的成员和朋友

        这不是你的情况

      2. 由会员和朋友(直到 从 Base 派生的任何类的 C++17),但仅在对 从 Base 派生的类型的对象(包括 this)

        这是你的情况,但参数 b 不是这样的派生类型

      受保护成员访问的原因是允许基类定义一个接口供派生类使用。这与允许每个不同的派生类型对每个基类对象进行特殊访问相同。

      【讨论】:

        【解决方案4】:

        您问题中的代码看起来像cppreference 网站中的示例,我们可以在代码 cmets 中看到对该限制的很好解释:

        struct Base {
         protected:
           int i;
         private:
           void g(Base& b, struct Derived& d);
        };
        
        struct Derived : Base {
           void f(Base& b, Derived& d) // member function of a derived class
           {
              ++d.i; // okay: the type of d is Derived
              ++i; // okay: the type of the implied '*this' is Derived
        //    ++b.i; // error: can't access a protected member through Base
        //             (Otherwise it would be possible to change other derived classes, 
        //                  like a hypothetical Derived2, base implementation)
            }
        };
        

        所以,如果你有一个

        class Derived2: public Base {
        };
        

        不应允许Derived 类访问Derived2 受保护的属性,因为它不是Derived2 的子级。 protected 的目的不是允许兄弟姐妹而是子类访问成员。

        标准中的完整细节:

        【讨论】:

        • 如果没有完整的示例,则不清楚b.i 是什么以及它为什么会导致错误
        • 你是对的。添加了完整的示例。
        猜你喜欢
        • 2019-01-20
        • 2014-08-27
        • 2012-08-29
        • 1970-01-01
        • 2023-03-18
        • 2018-11-27
        • 2016-04-07
        相关资源
        最近更新 更多