从公共接口继承时,为什么实现是公共的还是私有的并不重要?

时间:2011-06-27 12:47:23

标签: c++ inheritance virtual

我可能非常疲惫或者离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 ++中调用?

3 个答案:

答案 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()。因此,编译器没有看到任何问题,因为调用成员函数的要求符合它。

另请注意,可访问性(publicprivateprotected)是编译时构造。在运行时,没有这样的事情。编译器只能在编译时检测到与可访问性相关的规则的任何违反。它无法知道运行时会发生什么。

因此,即使i指向Usage部分中已定义bb()的类型为private的对象,编译器也可以使用它,如前所述static类型的i类型Interface*仍然是public,其bb()函数{{1}}。编译器不会打扰动态类型的对象以及它如何覆盖该函数,因为它不能,正是因为它的动态;它在运行时确定。

答案 2 :(得分:-1)

private表示您无法继承它。您可以继承protectedpublic,但没有什么可以阻止您将可见性限制在较低级别(即publicprotectedprivate;或{在您的顶级班级中{1}}到protected