我有这样的代码:
struct A {
virtual void f() {}
};
struct B: A {
private:
void f() override {}
};
...
B b;
A& a = b;
a.f();
当然,它会从B
调用f()
,因为在编译时检查了private,但选择虚拟函数版本是在运行时。在这种情况下,我可以禁止f()
呼叫吗?
否。当您在A
引用上调用f()
时,会在A
上检查访问规则。您不能期望编译器检查B
的规则,因为它不一定知道a
的类型是B
。
来自cppreference:
虚拟函数名称的访问规则在调用点使用用于表示调用成员函数的对象的表达式类型进行检查。忽略最后一个覆盖者的访问:
struct B { virtual int f(); }; // f is public in B
class D : public B { private: int f(); }; // f is private in D
void f() {
D d;
B& b = d;
b.f(); // OK: B::f is public, D::f is invoked even though it's private
d.f(); // error: D::f is private
}
不过,您的代码不应该依赖于此。在我看来,给定方法的访问说明符在整个类层次结构中应该是一致的。