Access a derived private member function from a ba

2019-06-16 20:04发布

问题:

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 ?

回答1:

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.



回答2:

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



回答3:

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.



回答4:

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.