Cannot access protected member of base class in derived class

后端 未结 4 740
渐次进展
渐次进展 2021-01-07 19:01

I have the following code:

struct A {
protected:
    A() {}

    A* a;
};

struct B : A {
protected:
    B() { b.a = &b; }

    A b;
};

相关标签:
4条回答
  • 2021-01-07 19:07

    There are actually two separate problems here.

    The first is that the line doesn't just do an assignment, but tries to initialize the base class (which works fine) and the member b. To create the b member it needs to construct it, and as a member it needs public access to a constructor, which it doesn't have.

    Then the assignment also is unable to access non-public member of b because again, it's not of type B but type A instead.

    Remember that protected means you can access parts of A through a B object (or child) only.

    In this case tell us your real problem and we can try to help solve it. Inheriting and composing from the same type is a design smell.

    0 讨论(0)
  • 2021-01-07 19:09

    The meaning of protected is that the derived type will have access to that member of its own base and not of any random object*. In your case, you care trying to modify b's member which is outside of your control (i.e. you can set this->a, but not b.a)

    There is a hack to get this to work if you are interested, but a better solution would be to refactor the code and not depend on hacks. You could, for example, provide a constructor in A that takes an A* as argument (this constructor should be public) and then initialize it in the initializer list of B:

    A::A( A* p ) : a(p) {}
    B::B() : b(&b) {}
    

    * protected grants you access to the base member in any instance of your own type or derived from your own type.

    0 讨论(0)
  • 2021-01-07 19:25

    It seems like a big limitation of the C++ language. How would you solve problem like this:

    class Node
    {
    public:
     void Save();
    protected:
     virtual void SaveState(int type) = 0;
    };
    
    class BinaryNode : public Node
    {
    protected:
     Node *left;
     Node *right;
    
     virtual void SaveState(int type) override
     {
        left->SaveState(type);
        right->SaveState(type);
     }
    };
    

    In this example I do not want to make method SaveState visible outside Node hierarchy. Only method Save should be public.

    0 讨论(0)
  • 2021-01-07 19:29

    All the compilers that I tested complained about several things, and specifically the protected constructor would be a problem even if the assignment statement were removed.

    You don't get to access the protected members of any instance of a type you derive from. This issue is clarified in the examples of 11.4p1.

    class B {
    protected:
      int i;
      static int j;
    };
    
    class D1 : public B {
    };
    
    class D2 : public B {
      void mem(B*, D1*);
    };
    
    void D2::mem(B* pb, D1* p1) {
      pb->i = 1; // ill-formed
      p1->i = 2; // ill-formed
      // ...
    }
    
    0 讨论(0)
提交回复
热议问题