与Private function member called outside of class一样,可以编写以下代码:
#include <iostream>
class A {
public:
virtual void f() { std::cout << "A::f()"; }
};
class B : public A {
private:
void f() override { std::cout << "B::f()"; }
};
void g(A &g) { g.f(); }
int main() {
A a;
g(a);
a.f();
B b;
g(b);
b.f(); // compilation failure
}
当然,编译器拒绝编译最后一行,因为代码的静态分析显示B::f()
已定义但是私有。
严重困扰我的是与概念概括/专业化的关系。通常认为您必须能够操纵子类型的实例,至少与操作超类型实例的方式相同。
这是Liskov's substitution principle的基础。在给定的示例中,当使用类型为g()
的参数或类型为A
的参数调用B
时,这会得到尊重。但最后一行不被接受,似乎在这种情况下,取代原则以某种方式被违反(考虑在宏定义#define h(x) (x.f())
中按名称调用)。
即使有人可能认为Liskov的原则没有被违反(宏不是语言的真正部分,那么好),最后一行给出编译时错误的事实,至少意味着类型为{的对象{1}}无法被操纵,因为B
可以。因此即使推导为A
,B
也不是A
的特化。
因此,在C ++中,使用public
派生并不能保证您有效地实现了专门化。您需要考虑代码的更多属性,以确保您具有“正确”的专业化。
我错了吗?有人能给我一个理由吗?我想要一个很好的语义论证,我的意思是至少比Stroustrup更精细的东西比如'C ++试图不约束你,如果你想要你可以自由使用它而不是你不想要'。我认为语言需要建立在一个合理的模型上,而不是一大堆可能的技巧。