C++ 从指向派生对象的基类指针访问派生私有成员函数
可能重复:C++ 从指向派生对象的基类指针访问派生私有成员函数,c++,inheritance,polymorphism,access-modifiers,C++,Inheritance,Polymorphism,Access Modifiers,可能重复: #包括 使用名称空间std; B类{ 公众: 虚空fn1(虚空){cout访问修饰符,如public、private和protected仅在编译期间强制执行。当您通过指向基类的指针调用函数时,编译器不知道指针指向派生类的实例。根据规则,编译器可以由此推断表达式,此调用有效 降低派生类中成员的可见性通常是一种语义错误。Java和C等现代编程语言拒绝编译此类代码,因为基类中可见的成员总是可以通过基指针在派生类中访问。调用p->fn2()在运行时根据p所指向的对象类型进行计算。在编译时,
#包括
使用名称空间std;
B类{
公众:
虚空fn1(虚空){cout访问修饰符,如public
、private
和protected
仅在编译期间强制执行。当您通过指向基类的指针调用函数时,编译器不知道指针指向派生类的实例。根据规则,编译器可以由此推断表达式,此调用有效
降低派生类中成员的可见性通常是一种语义错误。Java和C等现代编程语言拒绝编译此类代码,因为基类中可见的成员总是可以通过基指针在派生类中访问。调用p->fn2()
在运行时根据p
所指向的对象类型进行计算。在编译时,编译器将p->fn2()
调用视为对B::fn2()
的调用,并且由于B::fn2()
是公共的,编译器不会只报告错误。只有在运行时,实际的函数调用才是D::fn2()
进行评估
这并没有破坏<代码>封装< /COD>原理。这是C++的一个特性,叫做“代码>运行时多态性或<代码>动态多态性
:
在OOP中,当派生类继承
基类,派生类的对象
类别可被称为(或铸造)
要么是基类类型,要么是
派生类类型。如果存在
基类方法被
派生类,方法调用
行为模棱两可
虚拟与虚拟的区别
非虚拟解决了这种歧义。
如果所讨论的函数是
在基类中指定为“虚拟”
然后是派生类的函数
将被调用(如果存在)。如果
不是虚拟的,基类的
函数将被调用
HTH.当您执行p=new D
时,p->\uu vfptr
现在指向D
的虚拟函数表的开始。由于这是在运行时发生的,因此访问说明符不会起作用。这并没有回答OP关于访问修饰符的问题。我们也不会就此写签名。第11.6 i节n C++99。由于未指定,D中的fn1默认为私有。@Georg:垃圾问题标题如何帮助打破堆栈溢出的有趣示例。这个问题的标题很棒。@Tomalak Geret'kal您可以随时编辑其他问题以使用相同的标题。我正在考虑这样做。您认为如何?@Georg:Cheers:D我投t票o带着沉重的心情以dup结束这个问题。对不起,巴拉斯。@Hosam:已经完成了。虚拟函数表是一个实现细节。vptr
&vtbl
是编译器的实现细节,所以用它们来解释不是最好的方法。
#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();
}