父类中受保护的数据在子类中不可用? 我感到困惑:我认为受保护的数据是由C++中给定类的孩子读写的。

父类中受保护的数据在子类中不可用? 我感到困惑:我认为受保护的数据是由C++中给定类的孩子读写的。,c++,protected,C++,Protected,以下代码段无法在MS编译器中编译 class A { protected: int data; }; class B : public A { public: B(A &a) { data = a.data; } }; int main() { A a; B b = a; return 0; } 错误消息: Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.

以下代码段无法在MS编译器中编译

class A
{
protected:
  int data;
};

class B : public A
{
  public:

  B(A &a)
  {
    data = a.data;
  }
};

int main()
{
  A a;
  B b = a;
  return 0;
}
错误消息:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
        demoFail.cpp(4) : see declaration of 'A::data'
        demoFail.cpp(2) : see declaration of 'A'

我做错了什么

B的构造函数是私有的。如果未指定任何内容,则在类中,默认修饰符是private(对于结构,它是public)。因此,在本例中,问题是您无法构造B。当您将public添加到构造函数B时,另一个问题出现:

B有权修改A的一部分,但在这种情况下,B无权修改A的另一部分

您可以执行以下操作:

class A
{
public:
  A()
      : data(0)
  {
  }
  A(A &a)
  {
    data = a.data;
  }
protected:
  int data;
};

class B : public A
{
public:
  B(A &a)
      : A(a)
  {
  }
};

int main()
{
  A a;
  B b = a;
  return 0;
}

根据TC++PL,第404页:

派生类只能为其自身类型的对象访问基类的受保护成员。。。。这可以防止在一个派生类损坏属于其他派生类的数据时发生细微错误

当然,这里有一个简单的方法来解决您的案例:

class A
{
protected:
    int data;
};

class B : public A
{
public:
    B(const A &a)
        : A(a)
    {
    }
};

int main()
{
    A a;
    B b = a;
    return 0;
}

C++标准中关于保护非静态成员在<代码> 11.5/1 < /COD>

当派生类的友元函数或成员函数引用基类的受保护的非静态成员函数或受保护的非静态数据成员时,除第11条前面所述的检查外,还应进行访问检查。除非形成指向成员的指针(5.3.1),否则访问必须通过指向派生类本身(或派生自该类的任何类)的指针、引用或对象(5.2.5)。如果访问要形成指向成员的指针,嵌套名称说明符应命名派生类(或从该类派生的任何类)

除了修复其他人之前提到的问题(B的构造函数是私有的),我认为rlbond的方法可以很好地解决这个问题。然而,本标准上述段落的一个直接结果是,使用成员指针可以实现以下操作,当然,这可以说是类型系统中的一个漏洞

class B : public A {
public:
  B(A &a){
    int A::*dataptr = &B::data;
    data = a.*dataptr;
  }
};
当然,不建议您使用此代码,但它表明您可以访问它,如果您确实需要的话(我看到这种方法被用于打印
std::stack
std::queue
std::priority\u queue
,通过访问其受保护的容器成员
c
)您不应该在
B
构造函数中复制
A
对象。其目的是将
A
成员的初始化留给它自己的构造函数:

struct A { 
  A( const A& a ): data( a.data ) {}
  protected: int data; 
};

struct B : public A {
  B( const A& a ): A( a ) {}
};

我就是这么想的,但这不是问题所在。@jde:事实上,这是个打字错误。将B的构造函数公之于众会产生相同的错误。@Paul,请修复问题中的任何意外错误,因此进一步的回答不会提出相同的解决方案:)嗯。准确地说,这个案例是一个虚拟案例,只是为了说明问题。实际上,我想对传入的数据进行一些相当密集的读取。在任何情况下,您只能在这个或另一个B对象的A部分中处理受保护的数据。如果您有一个同样从A派生的A实例或C实例,那么B对这些As没有特殊的权限。如果您不能接受此建议(通过将其复制为B的基本部分,使其成为B的一部分,您确实有权访问),那么您可能会遇到设计问题,可能需要更大的图片来回答。@rlbond:睡前编码再次出现。这确实解决了我的问题。谢谢。:)您好Johannes Schaub-litb您能告诉我如何访问std::stack或std::queue中的受保护成员c吗?我在访问它时遇到问题。它给了我一个错误C2248:“std::stack::c”:无法访问类“std::stack”中声明的受保护成员谢谢