我可能非常疲惫或者离C ++太远了,但今天这个让我感到惊讶:
#include <iostream>
class Interface
{
public:
virtual int aa() const = 0;
virtual int bb() const = 0;
};
class Usage : public Interface
{
private:
virtual int aa() const
{
int a = 10 * 10;
return a;
}
virtual int bb() const
{
int b = 20 * 20;
return b;
}
};
int main(int argc, char* argv[])
{
Interface* i = new Usage();
std::cout << i->bb() << std::endl;
return 0;
}
我希望编译器和/或链接器会抱怨错误的函数签名或至少缺少实现。考虑到这是有效的,当它被顶级声明隐藏时,public / protected / private修饰符的含义是什么?
此规则如何在C ++中调用?
答案 0 :(得分:7)
这在标准第11.6.1段中有详细说明:
a的访问规则(第11条) 虚函数由其决定 声明并且不受影响 以后的函数规则 覆盖它。 [示例 - 与您的基本相同] 在呼叫点检查访问 使用所用表达式的类型 表示对象 调用成员函数。访问 在类中的成员函数 它的定义通常不是 已知的。
答案 1 :(得分:1)
Interface* i = new Usage();
std::cout << i->bb() << std::endl;
这是有效的,因为函数名称是根据对象的static
类型解析的。
此处对象为i
,其static
类型为Interface*
,其public
函数名为bb()
。因此,编译器没有看到任何问题,因为调用成员函数的要求符合它。
另请注意,可访问性(public
,private
和protected
)是编译时构造。在运行时,没有这样的事情。编译器只能在编译时检测到与可访问性相关的规则的任何违反。它无法知道运行时会发生什么。
因此,即使i
指向Usage
部分中已定义bb()
的类型为private
的对象,编译器也可以使用它,如前所述static
类型的i
类型Interface*
仍然是public
,其bb()
函数{{1}}。编译器不会打扰动态类型的对象以及它如何覆盖该函数,因为它不能,正是因为它的动态;它在运行时确定。
答案 2 :(得分:-1)
private
表示您无法继承它。您可以继承protected
或public
,但没有什么可以阻止您将可见性限制在较低级别(即public
到protected
或private
;或{在您的顶级班级中{1}}到protected
。