Possible Duplicate:
Why can i access a derived private member function via a base class pointer to a derived object?
#include <iostream>
using namespace std;
class B {
public:
virtual void fn1(void) {cout << "class B : fn one \n"; }
virtual void fn2(void) {cout << "class B : fn two \n"; }
};
class D: public B {
void fn1(void) {cout << "class D : fn one \n"; }
private:
void fn2(void) {cout << "class D : fn two \n"; }
};
int main(void)
{
B *p = new D;
p->fn1();
p->fn2();
}
Why does p->fn2()
call the derived class function even though fn2
is private in D
?
Access modifiers, such as public
, private
and protected
are only enforced during compilation. When you call the function through a pointer to the base class, the compiler doesn't know that the pointer points to an instance of the derived class. According to the rules the compiler can infer from this expression, this call is valid.
It is usually a semantic error to reduce the visibility of a member in a derived class. Modern programming languages such as Java and C# refuse to compile such code, because a member that is visible in the base class is always accessible in the derived class through a base pointer.
The call p->fn2()
is evaluated at run time depending on the type of objected pointed by p
. At compile time the compile sees the p->fn2()
call as call to B::fn2()
and since B::fn2()
is public the compiler doesn't report only error. It is only at runtime that actual function call D::fn2()
is evaluated.
This doesn't break the Encapsulation
principle this is a feature of C++ called Run-time Polymorphism
or Dynamic Polymorphism
When you do p = new D
, p->__vfptr
is now pointing to the start of the virtual function table of D
. And since this happens at runtime, therefore, access specifiers don't come into play.
From wikipedia:
In OOP when a derived class inherits a
base class, an object of the derived
class may be referred to (or cast) as
either being the base class type or
the derived class type. If there are
base class methods overridden by the
derived class, the method call
behaviour is ambiguous.
The distinction between virtual and
non-virtual resolves this ambiguity.
If the function in question is
designated "virtual" in the base class
then the derived class's function
would be called (if it exists). If it
is not virtual, the base class's
function would be called.
HTH.