#include <iostream>
struct A
{
virtual void foo(){ std::cout << "A"; };
};
struct B : public A
{
private:
void foo() override { std::cout << "B"; }
};
int main()
{
A *p = new B;
p->foo(); // prints B
// B b;
// b.foo(); // error: foo is private
return 0;
}
// g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp && ./a.out
Run Code Online (Sandbox Code Playgroud)
所以我们可以B.foo()多态地调用,但不能直接调用.当有人想要使用此功能时,是否有任何用例?
小智 5
它取决于基类的设计.假设你有一个基类
class Stream {
public:
virtual bool canSeek() = 0;
virtual void seek(int offset) = 0;
};
Run Code Online (Sandbox Code Playgroud)
注意:此示例来自.NET世界,其中基类库Stream类确实具有此类虚拟CanSeek属性.我不想讨论这是否是好的设计,因为我可以看到双方的有效论据.这样的基类在现实中存在就足够了.
现在,派生类可以指定它
class SpecificStream final : Stream {
private:
virtual bool canSeek() { return false; }
virtual void seek(int offset) { throw "no seek for you"; }
}
Run Code Online (Sandbox Code Playgroud)
在这个派生类中,实现的事实seek是因为它在技术上是必需的.但是,任何处理此问题的代码都已SpecificStream知道该seek函数对此类完全没用,因此不应调用.对基Stream类进行编码时,检查canSeek()结果并seek仅在结果为真时调用才有意义.对SpecificStream类进行编码时,检查是没有意义的canSeek(),因为它的结果是静态知道的,并且它通常没有意义调用seek().如果这样的调用是程序员错误,那么帮助编译器为这样的调用提供有用的消息是有意义的.
它阻止您以非多态方式调用方法,仅此而已:使用范围解析运算符直接访问方法可能会导致代码难以维护。在您知道并非每个人都是经验丰富的实现者的环境中(可能是为大型代码库做出贡献的科学程序员),引入模式来保护您的代码免受它们的侵害是值得的!
也就是说,Java 明确禁止它,因为他们认为这是不好的风格。