【问题标题】:Derived class cannot access the protected member of the base class派生类无法访问基类的受保护成员
【发布时间】:2019-01-20 07:40:21
【问题描述】:

考虑下面的例子

class base
{
protected :
    int x = 5;
    int(base::*g);
};
class derived :public base
{
    void declare_value();
    derived();
};
void derived:: declare_value()
{
    g = &base::x;
}
derived::derived()
    :base()
{}

据了解,只有基类的朋友和派生类可以访问基类的受保护成员,但在上面的示例中,我收到以下错误 "Error C2248 'base::x': cannot access protected member declared in class " 但是当我添加以下行时

friend class derived;

将其声明为朋友,我可以访问基类的成员,我在声明派生类时是否犯了一些基本错误?

【问题讨论】:

  • 好吧,derived 的构造函数是私有的,所以这个类很难使用,但我认为这不是问题所在。为什么不尝试使用更简单的访问方式呢?例如,一个只返回x 的派生类函数(提示:您无需指定base:: 即可访问它)
  • stackoverflow.com/questions/477829/… 会回答您的问题吗?非常相似。
  • 为什么不使用 just : g = &x; ?
  • @SebastianRedl 你链接的问题是关于在另一个实例上调用受保护的方法,这不是这里的情况
  • @user463035818 推理是一样的。您尝试通过不是您的类的访问路径访问受保护的成员。这就是为什么宋元瑶的回答有效。

标签: c++ class inheritance protected


【解决方案1】:

派生类只能通过派生类的上下文访问基类的protected 成员。换句话说,派生类不能通过基类访问protected成员。

当一个指向受保护成员的指针形成时,它必须使用派生的 声明中的类:

struct Base {
 protected:
    int i;
};

struct Derived : Base {
    void f()
    {
//      int Base::* ptr = &Base::i;    // error: must name using Derived
        int Base::* ptr = &Derived::i; // okay
    }
};

你可以改变

g = &base::x;

g = &derived::x;

【讨论】:

  • @user463035818 g = &x;?没有。&x 的类型为int*,不能分配给指向成员的指针。 LIVE
  • 这样做的原因是派生类只允许访问其自身类型的基保护成员。想象一个具有受保护成员的 Shape 基类。如果 Square 继承自它,我们不希望 Square 访问 Circle 的受保护成员。 (重点是,仅仅因为 X 继承自 Base 并不意味着 X 应该有权访问所有受 Base 保护的成员,只能访问那些被 X 类型的对象实际使用的成员。) base::qualification 不再在上下文中派生类,因此受保护的访问会阻止它。
  • &(foo::x)&foo::x 之间似乎有区别,我不知道(第一个是 int*,第二个是指向 int 成员的指针)
  • @user463035818 是的。对于这种情况,&(derived::x)&(x)&x 相同。
  • @Rick Protected 允许访问声明它的类的成员(和朋友),以及它的派生类。不允许的是,如果 X 是具有受保护成员的基,并且两个类 A 和 B 都派生自 X。A 只能在查看类型 A 的类时看到 X 的受保护成员(因为它是它自己的数据),但不是 X 在 B 类中的受保护成员,反之亦然。给定一个指向基址的指针,您不知道它实际上是指向 A 还是 B,因此不允许 A 看到 B 的受保护数据(反之亦然),这是不允许的。
【解决方案2】:

我的编译器实际上说我需要向base 添加一个非默认构造函数,因为该字段未初始化。

我添加后

base() : g(&base::x) {}

它确实编译没有问题。

【讨论】:

  • 这是有效的,因为您正在从 base 内部访问 base::x,这显然可以访问。
  • @ChrisUzdavinis 我没有删除任何行,在问题中给出错误的行仍然存在并且愉快地编译没有错误。我刚刚通过添加构造函数修复了其他错误。
猜你喜欢
  • 2012-08-29
  • 2016-04-07
  • 2013-10-21
  • 2015-12-30
  • 2014-08-27
  • 1970-01-01
  • 2016-02-29
  • 2012-05-02
  • 1970-01-01
相关资源
最近更新 更多