为什么虚函数违抗访问说明符? C++

Why virtual functions defy access specifiers ? C++

让我们假设你有一个 class base 和 class A 继承自 base 。 base 有一个名为 getValue() 的纯虚函数的声明,它是 public ,并且 A 包含设置为 private 的函数的定义(实现)。 当尝试使用从基引用或指针 (base& /base*) 到 A 对象的函数 getValue() 时,即使它被声明为 private

,它也会访问它

因为在 C++ 中,虚拟性和访问是正交的。当编译器看到 base*base& 并且需要对其调用 getValue 时,那么在 base.

中可以访问该函数就足够了

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


不过,这并不意味着在 class 层次结构中改变访问说明符是好的风格,因为它可能会造成混淆。事实上,您应该将 getValue 分成两个不同的函数,一个是虚拟函数,另一个是非虚​​拟函数。

长话短说:C++ 在这里的行为与其他流行的编程语言非常不同,因为它实际上允许并鼓励 private virtual 函数。 virtual成员函数默认是private的,public成员函数默认是non-virtual的,必要时调用private的virtual。 (当然,唯一的例外是析构函数。)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;
}