Why Can't I Access a Protected Member from an Instance of a Derived Class

Why can't I access a protected member from an instance of a derived class?

yes protected members are accessible by derived classes but you are accessing it in the main() function, which is outside the hierarchy. If you declare a method in the class B and access num it will be fine.

Cannot access protected member of another instance from derived type's scope

The rule in [class.access.base] is:

A member m is accessible at the point R when named in class N if [...]

  • m as a member of N is protected, and R occurs in a member or friend of class N, or in a member of a class P derived from N, where m as a member of P is public, private, or protected

There's a lot of letters in there. But there are basically two conditions:

  1. R is in a member or friend of the class. This handles the d.prot example - we are in a member of Derived while accessing a protected member of Derived.
  2. R is in a member of a derived class and the member being accessed is a member of the derived class instance. This handles the b.prot example - we are in a member of a derived class, but prot is not a member of the derived class.

In other words, Derived can access Base's protected members - but only in the case that it is accessing its own subobject's protected members. It cannot access other Base object's protected members. This makes sense when you consider that this other Base could easily be SomeOtherDerived, in which case that's just another unrelated object to us that we have no special access privileges to.

Derived class cannot access the protected member of the base class

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;

Why can't I access a protected member from an instance of a base class?

You can access the protected members of a base class only through a pointer or reference to an object of the derived type.

If you change

void copy_a_from_bar(bar& o){
a = o.a;
}

to

void copy_a_from_bar(bar& o){
foo& foo_ref = o;
a = o.a; // OK. Accessing it through `bar&`
a = foo_ref.a; // Not OK. Accessing it through `foo&`
}

you will see the same error.

This SO answer gives an indication of why allowing access to the protected members of the base class will be a potential breach of the protected status of the base class members.

Say you have:

class baz : public foo
{
void update_a(foo& f)
{
f.a = 20;
}
};

and use:

bar x;
baz z;
z.update_a(x);

If this were allowed, baz will be able to change the values of members of bar. That is not good.

C++: Why Protected Constructor Cannot be Accessed in the Derived Class?

protected members could be accessed from derived class, but only when through the derived class.

A protected member of a class is only accessible

  1. ...
  2. to the members and friends (until C++17) of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:

So you can't create an indpendent object of base class even in member functions of derived class.

Put it in another way, the protected members of the current instance of derived class could be accessed, but protected members of independent base class can't. E.g.

class A {
protected:
int x;
public:
A() : x(0) {}
};

class B : public A {
public:
void g() {
this->x = 42; // fine. access protected member through derived class
A a;
a.x = 42; // error. access protected member through base class
}
};

Cannot access protected members from a derived class

It's exactly as you said. parentInstance could be an instance of ChildClass2, so exposing that object's protected members to your ChildClass would create a possible security threat.

Imagine the following scenario:

You have an extensible class A, which exposes some protected members to its derived classes (which might, for example, mutate protected state or call other, possibly virtual members) and a derived class B, which uses the base functionality to do some security critical stuff, while exposing only a safe API with all kinds of error and permission checking.

Now, would you really want anyone to be able to easily bypass those checks by simply deriving a class C from A which then could directly call the protected methods on an object of type B?

Accessing protected members in a derived class

A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.

In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.

Changing the constructor to take a Derived instance will solve the problem.

How can I access base class's protected members through derived class?

There is not more to it than you already discovered. Derived instances may acces their protected members and those of other derived instances but not those of base class instances. Why? Because thats how protected works by definition.

For more details I refer you to cppreference (emphasize mine):

A protected member of a class Base can only be accessed

1) by the members and friends of Base

2) by the members and friends (until
C++17) of any class derived from Base, but only when operating on an
object of a type that is derived from Base (including this)

Why can't I access a protected member variable of a base class passed into a function as an argument?

In this answer I'll assume that you used public inheritance in your code (which was missing from the question).


[C++11: 11.2/1]: If a class is declared to be a base class (Clause 10) for another class using the public access specifier, the public members of the base class are accessible as public members of the derived class and protected members of the base class are accessible as protected members of the derived class. If a class is declared to be a base class for another class using the protected access specifier, the public and protected members of the base class are accessible as protected members of the derived class. If a class is declared to be a base class for another class using the private access specifier, the public and protected members of the base class are accessible as private members of the derived class.

This covers the case where you're accessing a member of the same object.

However, it's a little curiosity of protected member access that in order to access a protected member of another object, it has to be located within the definition of the same type or a more derived type; in your case, it is in a less-derived type (i.e. a base):

[C++11: 11.4/1]: An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2) As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.

That is, you'd have to run this code from within a Class1 member function.

Bjarne mentions this in his book The C++ Programming Language (Sp. Ed.) on page 404:

A derived class can access a base class' protected members only for objects of its own type [...] This prevents subtle errors that would otherwise occur when one derived class corrupts data belonging to other derived classes.



Related Topics



Leave a reply



Submit