Below is a subtle example of accessing an instance\'s protected field x. B is a subclass of A so any variable of type B is also of type A. Why can B::foo() access b\'s x fie
Class B
is not identical to class A
. That's why members of class B
cannot access non-public members of class A
.
On the other hand, class B
derives publicly from class A
, so class B
now has a (protected) member x
which any member of class B
can access.
In Public Inheritance:
All Public members
of the Base Class become Public Members
of the derived class &
All Protected members
of the Base Class become Protected Members
of the Derived Class
.
As per the above rule:
protected member x
from A
becomes protected member of class B
.
class B
can access its own protected members in its member function foo
but it can only access members of A
through which it was derived not all A
classes.
In this case, class B
contains a A
pointer a
, It cannot access the protected members of this contained class.
Why can the B::foo()
access the members of the contained class B
pointer b
?
The rule is:
In C++ access control works on per-class basis, not on per-object basis.
So an instance of class B
will always have access to all the members of another instance of class B
.
An Code Sample, which demonstrates the rule:
#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;
}
Since B
is publicly inherited from A
, A's protected member(s) become B's protected member(s), so B can access its protected members as usual from its member function(s). That is, the objects of B
can access the protected members of B
from its member functions.
But A's protected members cannot be accessed outside the class, using object of type A
.
Here is the relevant text from the Standard (2003)
11.5 Protected member access [class.protected]
When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class).
And the example follows from the Standard (2003) itself as:
[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]
Note in the above example fr()
is a friend function of D2
, mem()
is a member function of D2
, and g()
is neither a friend, nor a member function.
Consider:
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.
}
};
Why can B::foo() access b's x field, but not a's x field?
A protected member can only be accessed by other members of the same class (or derived classes).
b->x
points to a protected member of an instance of class B (through inheritance), so B::foo()
can access it.
a->x
points to a protected member of an instance of class A, so B::foo()
cannot access it.
Lets start with basic concept,
class A {
protected:
int x;
};
class B : public A {
public:
void foo() {
int u = x; // OK : accessing inherited protected field
}
};
Since child is inheriting parent, child gets x. Hence you can access x directly in foo() method of child. This is the concept of protected variables. You can access protected variables of parent in child directly. Note : Here I am saying you can access x directly but not through A's object! Whats the difference ? Since, x is protected, you cannot access A's protected objects outside A. Doesnt matter where it is - If its main or Child . That's why you are not able to access in the following way
class B : public A {
protected:
A *a;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Here comes an interesting concept. You can access a private variable of a class using its object with in the class!
class dummy {
private :
int x;
public:
void foo() {
dummy *d;
int y = d->x; // Even though x is private, still you can access x from object of d - But only with in this class. You cannot do the same outside the class.
}
};
//Same is for protected variables.Hence you are able to access the following example.
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int y = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
Hope it explains :)
C++ is complete Object Oriented Programming, where as Java is pure Object oriented :)