2

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.

user258367
  • 3,247
  • 2
  • 18
  • 17
  • I suppose this is the equivalent of explicitly implementing an interface in C#. And instead of breaking encapsulation perhaps you are strengthening it. But, yes I guess it is a bit confusing. – satnhak Apr 16 '11 at 09:23
  • 1
    possible duplicate of [Public virtual function derived private in C++](http://stackoverflow.com/questions/1061726/public-virtual-function-derived-private-in-c) – Mat Apr 16 '11 at 09:24
  • also see http://stackoverflow.com/questions/484592/overriding-public-virtual-functions-with-private-functions-in-c – Mat Apr 16 '11 at 09:25
  • hi Mat, Will appreciate if you can tell me some tips to find duplicate questions. – user258367 Apr 16 '11 at 09:31
  • @user258367: When you type the question, use proper keywords as lookup list of probable matches appears based on what you type. Open the relevant ones and see if it is similar to your question. Other way is to use google, ex: This Q of yours can be searched in google by searching keywords: `virtual + private + access + site:stackoverflow.com` it gives results specific to stackoverflow.com..Hth – Alok Save Apr 16 '11 at 12:12

3 Answers3

6

The call bptr->f() is evaluated at run time depending on the type of objected pointed by bptr. At compile time the compile sees the bptr->f() call as call to B::f() and since B::f() is public the compiler doesn't report only error. It is only at runtime that actual function call D::f() is evaluated.

This doesn't break the Encapsulation principle this is a feature of C++ called Run-time Polymorphism or Dynamic Polymorphism

You cannot directly call dptr->f() because D::f() is declared under Private Access specifier and You cannot access privately declared members from outside the class.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

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.

pic11
  • 14,267
  • 21
  • 83
  • 119
2

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 of bptr is B which has a public function f() defined, so the expression bptr->f() passes the compiler's test. Hence it works.

But dptr->f() doesn't work, since the static type of dptr is D which has a private function f(), 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?

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851