Access to public base classes protected functions in objects differentfrom this

D

Daniel Aarno

Can anyone provide a good explanation to why the following does not
work? After all since A is a public base of B objects of type B ISA
object of type A.

class A {
protected:
void foo() {}
};

class B : public A {
public:
void bar(A &a, B &b) {
foo(); //< OK, accessing A::foo in *this
b.foo(); //< OK, accessing A::foo in other object of type B
a.foo(); //< ERROR: foo() is protected in this context
}
}

/Daniel
 
S

Sharad Kala

Daniel Aarno said:
Can anyone provide a good explanation to why the following does not
work? After all since A is a public base of B objects of type B ISA
object of type A.

Protected members are accessible to objects of same type, or a type derived
from the accessing class.
class A {
protected:
void foo() {}
};

class B : public A {
public:
void bar(A &a, B &b) {
foo(); //< OK, accessing A::foo in *this
b.foo(); //< OK, accessing A::foo in other object of type B

a.foo(); //< ERROR: foo() is protected in this context

Here type A is not the same as type B (from where you are accessing) and is
also NOT a type derived from B.

Sharad
 
A

Alf P. Steinbach

* Daniel Aarno:
Can anyone provide a good explanation to why the following does not
work? After all since A is a public base of B objects of type B ISA
object of type A.

class A {
protected:
void foo() {}
};

class B : public A {
public:
void bar(A &a, B &b) {
foo(); //< OK, accessing A::foo in *this
b.foo(); //< OK, accessing A::foo in other object of type B
a.foo(); //< ERROR: foo() is protected in this context
}
}

It's not 100% clear-cut, but a practical language design decision.

Consider a class B2 also deriving from A, and

class B: public A
{
void bar( A& a, B2 &b2 )
{
}
}


Why shouldn't code in class B be able to access the protected member
in 'b2'?

Well, we don't know that that's safe, in any way. In class B2 it might
be a requirement that the object is in a certain state before the
call. Or it might be that some further action is required after the
call to bring 'b2' to a valid external state; the function is protected
precisely because its usage requires knowledge of and access to the
the inner workings of the object, which is the opposite of encapsulation.

Now consider your original example, but called with an object of class C
as actual argument for 'b', where class C is derived from B. Again the
code in class B doesn't know whether its safe to call the protected
member function, because class C might have imposed additional requirements.
The reason this is not 100% clear-cut is that class B might have as part
of its contract that no derived class should change the requirements.
 
D

Daniel Aarno

Sharad said:
Protected members are accessible to objects of same type, or a type derived
from the accessing class.

Isn't B the accessing class? I don't think A::foo would be accessible from a
class C derived from the accessing class B.

Looking in The C++ programming language (Stroustrup S.E 2001) it sez the
follosing about a protected member:

"...its name can be used only by member functions and friends of the class in
which it is declared and by member functions and friends of classes derived
from this class."

This would make me think that:
a.foo();
b.foo();
should either booth fail or both succede

Anyone have any insight to what exactly the standard sez about this?
 
J

John Harrison

Daniel Aarno said:
Isn't B the accessing class? I don't think A::foo would be accessible from a
class C derived from the accessing class B.

B is the accessing class but the pointer is of type A*.

There are two requirements for protected access - the accessing class must
be the same as or derived from the class containing the protected member AND
the pointer must be the same as or derived from the accessing class.

The second requirement is often overlooked.

John
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* Daniel Aarno:

It's not 100% clear-cut, but a practical language design decision.

Consider a class B2 also deriving from A, and

class B: public A
{
void bar( A& a, B2 &b2 )
{
}
}


Why shouldn't code in class B be able to access the protected member
in 'b2'?

Well, we don't know that that's safe, in any way. In class B2 it might
be a requirement that the object is in a certain state before the
call. Or it might be that some further action is required after the
call to bring 'b2' to a valid external state; the function is protected
precisely because its usage requires knowledge of and access to the
the inner workings of the object, which is the opposite of encapsulation.

Now consider your original example, but called with an object of class C
as actual argument for 'b', where class C is derived from B. Again the
code in class B doesn't know whether its safe to call the protected
member function, because class C might have imposed additional requirements.
The reason this is not 100% clear-cut is that class B might have as part
of its contract that no derived class should change the requirements.

Uhm, I wrote something dumb here -- please ignore.

Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top