1

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

但是,在 C++ 中似乎是不可能的。我要么以常规方式声明方法

void Foo::Method()

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

void virtual Foo::Method() = 0;

然后方法变为虚拟,但我想避免这种情况以节省一点性能。

看来我想要那样的东西

void Foo::Method() = 0;

但这将是编译错误

4

3 回答 3

3

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

如果未实现使用的函数,则使用派生类的代码将无法编译和链接

否则,对于运行时多态,它需要是虚拟的,否则它不会被调用

于 2013-03-13T18:04:43.673 回答
2

我相信您可能会对 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# 中,如果要调用派生实现,也需要将方法设为虚拟。

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

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

如果你想避免虚拟调用的成本,你应该通过模板使用编译时多态性

于 2013-03-13T18:28:44.480 回答
0

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

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

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

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

但是,您可以通过定义一个模板来手动验证这些约束是否得到遵守,该模板将期望一个具有已定义方法或属性的类作为参数,并在要验证的类上使用该模板。我想这可以被认为是一种单元测试形式。

于 2013-03-13T18:12:30.620 回答