从基类指针访问派生的私有成员函数到派生对象

时间:2011-05-11 09:05:00

标签: c++ inheritance polymorphism access-modifiers

  

可能重复:
  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();
}

为什么p->fn2()调用派生类函数,即使fn2中的D是私有的?

4 个答案:

答案 0 :(得分:5)

访问修饰符,例如publicprivateprotected仅在编译期间强制执行。通过指向基类的指针调用函数时,编译器不知道指针指向派生类的实例。根据编译器可以从该表达式推断出的规则,此调用有效。

降低派生类中成员的可见性通常是语义错误。现代编程语言(如Java和C#)拒绝编译此类代码,因为在基类中可见的成员始终可以通过基指针在派生类中访问。

答案 1 :(得分:0)

在运行时评估调用p->fn2(),具体取决于p指向的对象类型。在编译时,编译将p->fn2()调用视为对B::fn2()的调用,并且由于B::fn2()是公共的,编译器不会仅报告错误。只有在运行时才会评估实际的函数调用D::fn2()

这不违反Encapsulation原则这是C ++的一个名为Run-time PolymorphismDynamic Polymorphism

的功能

答案 2 :(得分:0)

执行p = new D时,p->__vfptr现在指向D虚拟函数表的开头。因此,由于这在运行时发生,因此访问说明符不起作用。

答案 3 :(得分:-2)

来自wikipedia

  

在派生类继承a的OOP中   基类,派生的对象   上课可以被称为(或演员)   要么是基类类型,要么是   派生类类型。如果有   由...重写的基类方法   派生类,方法调用   行为含糊不清。

     

虚拟和虚拟之间的区别   非虚拟解决了这种模糊性。   如果有问题的功能是   在基类中指定为“virtual”   那么派生类的功能   将被调用(如果它存在)。如果它   不是虚拟的,基类的   函数将被调用。

HTH。