是否存在私有公共虚拟方法的用例?

时间:2016-11-16 14:46:53

标签: c++11 visibility

#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

因此我们可以多态地调用B.foo(),但不能直接调用ORDER BY MyColumn ASC 。当有人想要使用此功能时,是否有任何用例?

2 个答案:

答案 0 :(得分:5)

这取决于基类的设计。假设你有一个基类

class Stream {
public:
  virtual bool canSeek() = 0;
  virtual void seek(int offset) = 0;
};

注意:此示例来自.NET世界,其中基类库Stream类确实具有此类虚拟CanSeek属性。我不想讨论这是否是好的设计,因为我可以看到双方的有效论据。现实中存在这样的基类就足够了。

现在,派生类可以指定

class SpecificStream final : Stream {
private:
  virtual bool canSeek() { return false; }
  virtual void seek(int offset) { throw "no seek for you"; }
}

在这个派生类中,实现seek的事实是因为它在技术上是必需的。但是,任何处理此SpecificStream的代码都已知道seek函数对此类完全没用,因此不应调用。在对基础Stream类进行编码时,检查canSeek()的结果并仅在结果为真时调用seek可能是有意义的。在对SpecificStream类进行编码时,检查canSeek()是没有意义的,因为其结果是静态已知的,并且调用{{1}无疑是没有意义的。 }。如果这样的调用是程序员错误,那么帮助编译器为这些调用提供有用的消息是有意义的。

答案 1 :(得分:2)

它阻止你以非多态方式调用方法,这就是全部:使用范围解析运算符直接访问方法会导致难以维护代码。在一个你不知道每个人都是经验丰富的实现者的环境中(科学程序员可能会为大型代码库做贡献),引入模式来保护你的代码是值得的!

也就是说,Java明确禁止它,因为他们认为它的风格很糟糕。