覆盖非虚拟功能是否"道德"?

ana*_*lyg 9 c++ virtual-functions

我已经使用了以下C++经验法则很长时间了:

如果类覆盖其基类中的函数,则应在基类中声明该函数virtual.

我想我从这个规则中遇到了一个例外.为了判断这是否合理,或者指出我的设计存在缺陷,我问的是这个问题.我想得到例子或更好的规则.


编辑:我试着在这里描述我的用例,我明白我并不需要继承!

我想问一个普遍的问题.谢谢你的回答!

Ash*_*sha 12

您无法覆盖非虚拟功能.您唯一能做的就是隐藏基类实现.但是这并没有为您提供虚函数提供的多态行为.


Joh*_*itb 11

我个人不喜欢这个,但有时它很有用.标准库也使用它:

stringstream ss;

/* Imagine you want to redirect all output that goes into "ss"
 * to "cout". The following does NOT work! */
ss.rdbuf(cout.rdbuf());
Run Code Online (Sandbox Code Playgroud)

为什么不起作用?因为stringstream隐藏ios::rdbuf了一个相同的命名函数,只提供对其内部的读访问std::stringbuf,而不是附加的缓冲区.您需要执行以下操作

ss.std::ios::rdbuf(cout.rdbuf());
Run Code Online (Sandbox Code Playgroud)

现在,附加到流的缓冲区不等于ss.rdbuf()返回的缓冲区.我个人不喜欢这个设计.


我曾经很好地利用了隐藏.在我看来,隐藏需要一个要求:

  • 行为应该是一样的.

在我的情况下,我有一个像这样的基类(不是真的很接近,但它传达了这种情况).

template<typename T>
struct A {
  void doSomething() {
    T t;
    t.doIt();
  }
};

class Foo;
struct B : A<Foo> {

};

B b;
Run Code Online (Sandbox Code Playgroud)

一个人打电话会发生什么b.doSomething()?它需要标题Foo,因为函数想要调用doIt类并创建该类型的变量.解决方法很简单

class Foo;
struct B : A<Foo> {
  void doSomething();
};

// and in the .cpp file:
#include "Foo.h"

void B::doSomething() {
  A<Foo>::doSomething();
}
Run Code Online (Sandbox Code Playgroud)

这样,我阻止了我B班级的每个用户都需要包含Foo的标题.只有B的cpp文件,它知道它取决于"Foo",必须这样做.

  • +1我不知道你可以使用`derived.Base :: method(args ...)`从外部调用基类中的方法. (3认同)