有没有办法不继承子类中函数的"虚拟性"?

Kar*_*aru 9 c++ virtual

在C++中是否有可能让一个类覆盖一个虚函数,但只有当通过超类调用该函数时才有虚拟调度(即,当它被静态类型化为子类时调用它)?我知道这不会发生什么,但有什么办法可以实现一些接近的目标吗?

想要这个的原因是我有两个类都暴露了一个flush()函数.在我的程序中绝大多数时间,我flush()直接调用我知道类型的子类对象,所以我不需要虚拟调度.但是我想在混合中添加一个超类,所以很少我可以将对其中一个类的实例的引用传递给一个doSomethingThenFlush()函数,它将flush()虚拟调用.

我知道我可以使用模板而不是虚函数,我知道我可以有两个不同的功能(例如flushVirtual(),刚刚调用flushNonVirtual(),并且flushNonVirtual()在任何地方调用我都不需要虚拟调度).但这些看起来有点像在一个主要是语法的问题上抛出代码.有没有更优雅的方式来实现这一目标?

也许更重要的是,有谁知道为什么虚拟性在C++中被继承?

struct Base
{
  virtual ~Base(){}
  virtual void func();
};

struct Derived : public Base
{
  void func(){}
};

void callVirtually(Base &base)
{
  base.func();//this will use virtual dispatch
}

void callStatically(Derived &derived)
{
  derived.func();//I don't want/need this to use virtual dispatch
}

int main()
{
  Derived derived;
  callVirtually(derived);
  callStatically(derived);
}
Run Code Online (Sandbox Code Playgroud)

Set*_*gie 8

虚拟性是继承的,因为你不知道某人是否会从你的进一步派生出来Derived.有人可以做一个MoreDerived可以传递给期望a的函数Derived&,当他们发现Derived所有虚拟函数的版本被称为而不是MoreDerived's 时,他们会感到难过.

如果你的意思是你不会继承,Derived所以你不想为虚拟函数调用付费,那么你运气不好,因为C++没有办法保证你不会从类中继承,这是必要的做你想要的.


Mat*_* M. 5

在C++ 03中,没有.

正如其他人所说,每当它可以评估对象的运行时类型时,它就是一个编译器优化(以及一个经常使用的)来进行去虚拟化.

但是,在C++ 0x中,我们得到两个新的关键字:override并且final两者都可以应用于成员函数(final也可以应用于类).

  • override:指定此函数覆盖基类中的虚函数,对于在不是这种情况时发出警告非常有用
  • final:指定在子类中不能覆盖此函数(虚拟).

你的班级将成为:

struct Derived : public Base
{
  void func() final {}
};
Run Code Online (Sandbox Code Playgroud)

注意:使用final并不要求编译器对函数调用进行虚拟化(从标准的角度来看),但是任何有价值的编译器都应该这样做.