带有受保护字段的微妙C++继承错误

wco*_*ran 42 c++ inheritance protected

下面是访问实例的受保护字段x的一个微妙示例.B是A的子类,因此B类型的任何变量也是A类型.为什么B :: foo()可以访问b的x字段,而不是a的x字段?

class A {
protected:
  int x;
};

class B : public A {
protected:
  A *a;
  B *b;
public:
  void foo() {
    int u = x;     // OK : accessing inherited protected field x
    int v = b->x;  // OK : accessing b's protected field x
    int w = a->x;  // ERROR : accessing a's protected field x
  }
};
Run Code Online (Sandbox Code Playgroud)

这是我用g ++得到的错误

$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is protected
A.cpp:14: error: within this context
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 25

由于B公开继承A,A受保护的成员成为B的受保护成员,因此B可以像往常一样从其成员函数访问其受保护的成员.也就是说,对象B可以B从其成员函数访问受保护的成员.

但是使用类型的对象,不能在类外部访问A的受保护成员A.

以下是标准(2003)的相关文字

11.5受保护的成员访问[class.protected]

当派生类的朋友或成员函数引用受保护的非静态成员函数或受保护的基类的非静态数据成员时,除了前面第11.102节中描述的那些之外,还应用访问检查.除非形成指向成员的指针(5.3) .1),访问必须通过指向,引用或派生类本身的对象(或从该类派生的任何类)(5.2.5).如果访问要形成指向成员的指针,则嵌套名称说明符应命名派生类(或从该类派生的任何类).

该示例遵循标准(2003)本身:

[Example:

class B {
  protected:
  int i;
  static int j;
};

class D1 : public B {
};

class D2 : public B {
  friend void fr(B*,D1*,D2*);
  void mem(B*,D1*);
};

void fr(B* pb, D1* p1, D2* p2)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  p2->i = 3; // OK (access through a D2)
  p2->B::i = 4; // OK (access through a D2, even though naming class is B)
  int B::* pmi_B = &B::i; // ill-formed
  int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
  B::j = 5; // OK (because refers to static member)
  D2::j =6; // OK (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  i = 3; // OK (access through this)
  B::i = 4; // OK (access through this, qualification ignored)
  int B::* pmi_B = &B::i; // ill-formed
  int B::* pmi_B2 = &D2::i; // OK
  j = 5; // OK (because j refers to static member)
  B::j = 6; // OK (because B::j refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  p2->i = 3; // ill-formed
}
—end example]
Run Code Online (Sandbox Code Playgroud)

以上示例fr()中的注释是友元函数D2,mem()是成员函数D2,g()既不是朋友,也不是成员函数.

  • 因为是公共继承,`A` 的受保护成员成为`B` 的受保护成员。不是私人的。 (2认同)
  • @David:在这种情况下,派生类显式地进行调用.我不知道受保护的继承与我们所谈论的内容有什么关系.纳瓦兹只谈论公共继承在发挥作用时会发生什么.(此外,我不了解你;我从未见过教科书以外的受保护遗产) (2认同)

Bil*_*eal 13

考虑:

class A {
protected:
  int x;
};

class C : public A
{
};

class B : public A {
protected:
  unique_ptr<A> a;
public:
  B() : a(new C) // a now points to an instance of "C"
  { }

  void foo() {
    int w = a->x;  // B accessing a protected member of a C? Oops.
  }
};
Run Code Online (Sandbox Code Playgroud)


Alo*_*ave 3

公共继承中:
所有Public members类都成为Public Members派生
所有Protected members都成为Protected Members派生类Derived Class

根据上述规则:
protected 成员x成为Aclass 的 protected 成员B

class B可以在其成员函数中访问自己的受保护成员foo,但只能访问A派生它的成员,而不是所有A类。

在这种情况下,class B包含一个A指针a,它无法访问这个包含类的受保护成员。

为什么可以访问包含的指针B::foo()的成员?class Bb

规则是:
在 C++ 中,访问控制基于每个类,而不是基于每个对象。
因此 的一个实例class B始终可以访问另一个 的实例的所有成员class B

代码示例,演示了该规则:

#include<iostream>

class MyClass 
{
    public: 
       MyClass (const std::string& data) : mData(data) 
       {
       }

       const std::string& getData(const MyClass &instance) const 
       {
          return instance.mData;
       }

    private:
      std::string mData;
};

int main() {
  MyClass a("Stack");
  MyClass b("Overflow");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)