如何声明必须实现而非虚函数

How to declare function which must be implemented and not virtual?

本文关键字:实现 函数 何声明 声明      更新时间:2023-10-16

我使用class来声明接口。我只想定义方法签名。此方法必须在任何非抽象子类中实现。我不需要方法是虚拟的。这是c#的默认行为BTW(我来自c#/Java世界)

然而在c++中这似乎是不可能的。我要么以常规方式声明方法

void Foo::Method()

,然后不强制实现它或将方法声明为"纯虚拟"

void virtual Foo::Method() = 0;

和method变成了虚拟的,但是我想避免这种情况,以节省一点性能。

似乎我也想要这样的东西

void Foo::Method() = 0;

但是这会导致编译错误

如果你打算从模板代码中使用派生类,即编译时多态性,那么你只需要记录预期的签名

如果使用的函数没有实现,那么使用派生类的代码将无法编译和链接

否则,对于运行时多态性,它需要是虚拟的,否则它将不会被称为

我相信你可能会对c#版本的工作方式感到困惑:

  class A {
    public void NonVirt() { Console.Out.WriteLine("A:NonVirt"); }
    public virtual void Virt() { Console.Out.WriteLine("A:Virt"); }
  }
  class B : A {
    public void NonVirt() { Console.Out.WriteLine("B:NonVirt"); }
    public override void Virt() { Console.Out.WriteLine("B:Virt"); }
  }
  class Program {
    static void Main(string[] args) {
      A x = new B();
      x.NonVirt();
      x.Virt();
    }
  }

这将输出

A:NonVirt 
B:Virt

因此,即使在c#中,如果你想调用派生实现,你也需要将方法设为virtual。

如果方法必须在所有非抽象子类中实现,这意味着您需要通过基类指针调用它们。这反过来意味着你需要使它们成为虚拟的,就像在c#中一样(也可能在Java中,但我不确定)

顺便说一句,在现代cpu上,虚拟调用的价格是几纳秒,所以我不确定它是否值得,但让我们说它是值得的。

如果想避免虚调用的开销,应该通过模板使用编译时多态性

c++中没有接口的概念。实现目标的唯一方法是创建一个定义为virtual= 0的基类,所有的方法必须在子类中实际定义。

class IBase {
      // ...
        virtual void f1() = 0;
      // ....
}

如果所有方法都像f1那样定义,该类将是虚纯的,这是您可以获得的最接近接口的。

在Java中接口的概念有点像实现它的类的契约。编译器通过检查实现者的内容来执行契约的约束。这种契约或显式结构子类型的概念在c++中并不正式存在。

然而,你可以通过定义一个模板来手动验证这些约束是否得到尊重,这个模板将期望一个类的参数具有定义的方法或属性,并在要验证的类上使用该模板。