I recently came across this article on IBM site. Below is the sample code
#include "iostream"
class B {
public:
virtual void f()
{
std::cout<<"\n In class B";
}
};
class D : public B {
private:
int i;
void f()
{
std::cout<<"\n In class D i = "<<i;
}
public:
D(int i_num):i(i_num)
{}
};
int main() {
D dobj(10);
B* bptr = &dobj;
D* dptr = &dobj;
// valid, virtual B::f() is public,
// D::f() is called
bptr->f();
// error, D::f() is private
//dptr->f();
}
We are now able to call private function of D.I wanted to know doesn't this break C++ encapsulation ?
P.S. : Please go to Virtual function access section in Virtual function. I do not know why I am not getting exact link when I do paste.
Access-specifiers are compile-time construct, and so, the compiler detects any violation of access-rules at compile-time (obviously) based on the static type of the object (or pointer). Such violation cannot be detected at runtime.
So
bptr->f()
works, because the compiler sees that the static type ofbptr
isB
which has apublic
functionf()
defined, so the expressionbptr->f()
passes the compiler's test. Hence it works.But
dptr->f()
doesn't work, since the static type ofdptr
isD
which has a private functionf()
, hence the code wouldn't even compile!Now whether it breaks encapsulation or not, is a very subjective question and will receive subjective answers. It entirely depends on how one defines it and the arguments directly flows from it. There is no one universal definition. My personal opinion is, if the language allows it, then (it would imply that) according to the C++ community, it doesn't break encapsulation, or if it does, then C++ allows it so as to achieve something very nobel (which otherwise isn't possible). Otherwise, I would say its just yet another misfeature of C++ just like the following:
Default argument in the middle of parameter list?
The call
bptr->f()
is evaluated at run time depending on the type of objected pointed bybptr
. At compile time the compile sees thebptr->f()
call as call toB::f()
and sinceB::f()
ispublic
the compiler doesn't report only error. It is only at runtime that actual function callD::f()
is evaluated.This doesn't break the
Encapsulation
principle this is a feature of C++ calledRun-time Polymorphism
orDynamic Polymorphism
You cannot directly call
dptr->f()
becauseD::f()
is declared underPrivate
Access specifier and You cannot access privately declared members from outside the class.It is by design.
B::f is public. User access of f via a pointer to B is allowed. Since f is virtual, the call would be dispatched to derived classes' f.
But D::f is private, you can't access f via a pointer do D.