12

Consider the following example

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() {} 

As per knowledge only friends and derived classes of the base class can access the protected members of the base class but in the above example I get the following error "Error C2248 'base::x': cannot access protected member declared in class " but when I add the following line

friend class derived; 

declaring it as friend , I can access the members of the base class , did I do some basic mistake in the declaring the derived class ?

8
  • Well, the constructor of derived is private, so the class will be tricky to use, but I don't think that's the problem. Why not try it using a simpler access? For example, a derived class function that just returns x (Hint: you won't need to specify base:: to access it) Commented Aug 13, 2018 at 14:28
  • Does stackoverflow.com/questions/477829/… answer your question? It's very similar. Commented Aug 13, 2018 at 14:30
  • 3
    why to not use just : g = &x; ? Commented Aug 13, 2018 at 14:30
  • @SebastianRedl the question you link is about calling a protected method on another instance, which isnt exactly the case here Commented Aug 13, 2018 at 14:32
  • @user463035818 The reasoning is the same though. You try to access a protected member through an access path that is not your class. Which is why songyuanyao's answer works. Commented Aug 13, 2018 at 14:36

2 Answers 2

13

The derived class could access the protected members of base class only through the context of the derived class. On the other word, the derived class can't access protected members through the base class.

When a pointer to a protected member is formed, it must use a derived class in its declaration:

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 } }; 

You can change

g = &base::x; 

to

g = &derived::x; 
Sign up to request clarification or add additional context in comments.

6 Comments

@user463035818 g = &x;? No. &x is with type int*, which can't be assigned to pointer to member. LIVE
The reason for this is that a derived class is only allowed to access the base protected members for its own type. Imagine a Shape base class with protected members. If Square inherits from it, we would not want Square to access the protected members of a Circle. (Point being, just because X inherits from Base doesn't mean X should have access to all Base protected members, only from those that are actually in use by objects of type X.) The base::qualification no longer is in the context of a derived class, and so the protected access prevents it.
there seems to be a difference between &(foo::x) and &foo::x i wasnt aware of (first is a int*, second is a pointer to int member)
@user463035818 Yes. For this case &(derived::x) is same as &(x) and &x.
@Rick Protected allows access to members (and friends) of the class that declares it, and also to its derived classes. What is NOT allowed is if X is a base with a protected member, and two classes A and B both derive from X. A can see protected member of X only when looking at classes of type A (since it is its own data), but not X's protected members in class B, and vice versa. Given a pointer to base, you don't know if it actually points to A or B, and so to disallow A from seeing B's protected data (and vice versa) it's just not allowed.
|
0

My compiler actually said I needed to add a non-default constructor to base because the field is not initialized.

After I added

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

it did compile without problems.

2 Comments

That's working because you are accessing base::x from inside base, which obviously will have access.
@ChrisUzdavinis I did not remove any lines, the line that is giving the error in the question is still there and happily compiling without errors. I just fixed the other errors by adding a constructor.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.