我正在使用类来声明接口。我只想定义方法签名。此方法必须在任何非抽象子类中实现。我不需要方法是虚拟的。这是C#BTW中的默认行为(我来自C#/ Java世界)
然而,在C ++中它似乎是不可能的。我要么以常规方式声明方法
void Foo::Method()
然后不是必须实现它或将方法声明为“纯虚拟”
void virtual Foo::Method() = 0;
然后方法变为虚拟,但我想避免这种情况以节省性能。
似乎我想要有类似的东西
void Foo::Method() = 0;
答案 0 :(得分:3)
如果你打算从模板代码中使用派生类,即编译时多态,那么你只需要记录预期的签名
如果未实现使用的函数,使用派生类的代码将无法编译和链接
否则,对于运行时多态性,它需要是虚拟的,否则不会被称为
答案 1 :(得分: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的虚拟通话价格只有几纳秒,所以我不确定它是否值得,但可以说它是。
如果要避免虚拟调用的成本,则应通过模板使用编译时多态性
答案 2 :(得分:0)
C ++中没有接口的概念。实现目标的唯一方法是创建一个基类,定义为virtual
和= 0
所有必须在子类中实际定义的方法。
class IBase {
// ...
virtual void f1() = 0;
// ....
}
如果所有方法都定义为f1
,那么该类将是虚拟纯的,这是最接近您可以获得的接口。
Java中的接口概念有点像实现它的类的契约。编译器通过检查实现者的内容来强制执行合同约束。契约或显式结构子类型的概念在C ++中不是正式存在的。
但是,您可以通过定义一个模板来手动验证是否遵守了这些约束,该模板将期望作为具有已定义方法或属性的类的参数,并在要验证的类上使用该模板。我认为这可以被视为一种单元测试形式。