可能重复:
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
是私有的?
答案 0 :(得分:5)
访问修饰符,例如public
,private
和protected
仅在编译期间强制执行。通过指向基类的指针调用函数时,编译器不知道指针指向派生类的实例。根据编译器可以从该表达式推断出的规则,此调用有效。
降低派生类中成员的可见性通常是语义错误。现代编程语言(如Java和C#)拒绝编译此类代码,因为在基类中可见的成员始终可以通过基指针在派生类中访问。
答案 1 :(得分:0)
在运行时评估调用p->fn2()
,具体取决于p
指向的对象类型。在编译时,编译将p->fn2()
调用视为对B::fn2()
的调用,并且由于B::fn2()
是公共的,编译器不会仅报告错误。只有在运行时才会评估实际的函数调用D::fn2()
。
这不违反Encapsulation
原则这是C ++的一个名为Run-time Polymorphism
或Dynamic Polymorphism
答案 2 :(得分:0)
执行p = new D
时,p->__vfptr
现在指向D
虚拟函数表的开头。因此,由于这在运行时发生,因此访问说明符不起作用。
答案 3 :(得分:-2)
来自wikipedia:
在派生类继承a的OOP中 基类,派生的对象 上课可以被称为(或演员) 要么是基类类型,要么是 派生类类型。如果有 由...重写的基类方法 派生类,方法调用 行为含糊不清。
虚拟和虚拟之间的区别 非虚拟解决了这种模糊性。 如果有问题的功能是 在基类中指定为“virtual” 那么派生类的功能 将被调用(如果它存在)。如果它 不是虚拟的,基类的 函数将被调用。
HTH。