为什么虚函数无法访问说明符? C ++

时间:2016-03-19 12:31:02

标签: c++ inheritance reference virtual-functions access-specifier

让我们假设你有一个继承自base的类库和类A. base有一个名为getValue()的纯虚函数的声明是公共的,A包含被设置为private的函数的定义(实现)。 当试图将基本引用或指针(base& / base *)中的函数getValue()用于A对象时,它会访问它,即使它被声明为私有

1 个答案:

答案 0 :(得分:2)

因为在C ++中,虚拟和访问是正交问题。当编译器看到base*base&并且需要在其上调用getValue时,只需在base中访问该函数即可。

A将{覆盖getValue声明为private这一事实无关紧要。毕竟,它怎么可能相关?在调用base.getValue()base->getValue()时,您不会知道您可能正在处理A。这首先是面向对象编程的重点!

这并不意味着在类层次结构中改变访问说明符是一种很好的风格,因为它可能会令人困惑。实际上,您应该将getValue分成两个不同的功能,一个是虚拟的,另一个是非虚​​拟的。

长篇故事:C ++在这方面与其他流行的编程语言有很大不同,因为它实际上允许并鼓励私有虚拟功能。默认情况下,虚拟成员函数应该是私有的,默认情况下,公共成员函数应该是非虚拟的,并在必要时调用私有虚函数。 (唯一的例外是析构函数。)Herb Sutter曾将此称为Non-Virtual Interface Idiom

示例:

#include <iostream>

class Base
{
public:
    virtual ~Base() {}

    int getValue() const
    {
        int const value = doGetValue();
        if (value < 0)
        {
            // error
        }
        return value;
    }

private:
    virtual int doGetValue() const = 0;
};

class A : public Base
{
private:
    int doGetValue() const override
    {
        return 123;
    }
};

int main()
{
    Base* ptr = new A; // use std::unique_ptr in real code
    std::cout << ptr->getValue() << "\n";
    delete ptr;
}