我对下面的代码段(g++ 4.4.7
)产生的输出感到惊讶。
class A {
public:
virtual void f() {std::cout << "A::f()" << std::endl;}
};
class B : public A {
private:
// Automatically virtual, because of base class
void f() {std::cout << "B::f()" << std::endl;}
};
int main(int argc, const char *argv[])
{
A *pB = new B();
pB->f();
return 0;
}
输出为
B::f()
我知道由于后期绑定,编译器无法在此处发出错误,但是为什么我们可以从非私有上下文调用私有方法?
理由是什么?
n3376 11.5.1
11.5.2虚函数的访问规则(第 11 条)由其声明决定,不受稍后覆盖它的函数的规则。
在调用点使用用于表示其对象的表达式类型检查访问调用成员函数。类中成员函数的访问它被定义(上面示例中的D)通常是未知的。
访问说明符仅用于编译目的。程序分配中的任何内存都可以由可执行文件的任何部分访问;运行时没有公共/私有概念
后期绑定函数是运行时,因此运行时没有公共和私有概念
我尝试执行此代码,只需进行少量修改即可指定基础
私人部分中的类虚拟函数,我从编译器收到错误。因为在编译
中 时间优先控件转到基类函数,但它在私有部分中定义,因此
编译器抛出错误。每当声明派生类的对象时,都会将
基类的引用。在编译时,控制首先转到基类,每个类 创建自己的虚拟表,然后在运行时指针对象调用派生类 功能,正如我之前所说,它被宣布为私有或公共无关紧要。
class A {
virtual void f() {std::cout << "A::f()" << std::endl;}
};
class B : public A {
private:
// Automatically virtual, because of base class
void f() {std::cout << "B::f()" << std::endl;}
};
int main(int argc, const char *argv[])
{
A *pB = new B();
pB->f();
return 0;
}