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