teo*_*ron 4 c++ polymorphism virtual inheritance
简单地说,如何在C++中为单级继承创建接口(出于简单和教学原因)?我看到一些代码没有使用多态,但基类包含一个虚拟抽象方法(virtual void TheMethod() = 0
).
现在,一个类是使用纯虚方法从这个抽象类派生的,但是在后续代码中,派生类的实例在没有动态分配的情况下被使用.
这是正确的方法吗?使用多态设计推断出的开销是多少?
我认为这是不可能的..这看起来更像隐藏/重影基本方法,即使该方法是纯虚方法.
后来编辑:感谢所有设法提供一些好答案的人,我想强调一下由于使用"动态分配"而产生的一个严重错误,强调这个对象创建的可能性是唯一一个兼容多态的.很明显,使用这种运行时调用行为并不是唯一的方法(但也许是最常见的?),但为了进一步澄清我原来的问题:
有没有办法强制程序员在不使用纯虚方法的情况下实现方法?我可能没有道理的关注是,打开多态设计的大门是否在性能方面也有点沉重(每秒钟对讨论中的方法进行数千次这样的调用).
甚至稍后编辑:使基础具有受保护的构造函数意味着它不能直接实例化(除了使用工厂或其他友好方法),这可以解决补偿纯虚方法引起的影响之一.但是如何确保任何派生类仍然提供自己的方法实现?如果对相关vtable的夸大担忧实际上并不是那么重要,那么我将坚持使用纯虚方法(因为SFINAE,奇怪的重复模板模式更难以阅读和理解至少中级C++程序员 - 像我一样:)).
您不必动态分配对象即可多态地使用它:
struct base {
virtual void foo() = 0;
};
struct derived : base {
virtual void foo() {
// do stuff
}
};
void f(base& object) {
object.foo();
}
int main() {
derived object; // no dynamic allocation at all
f(object); // polymorphism happens here
}
Run Code Online (Sandbox Code Playgroud)
出于教学原因,如果目标是了解如何在C++中实现多态对象,并测试已创建的类型,则不需要动态分配.但是,在实际的应用程序中,它可能会是,因为使用多态的主要原因是因为具体类型在运行时才会知道.
请注意,在C++中(以及几乎所有其他支持它的语言),多态性需要引用语义,而不是C++默认使用的值语义.通常,设计用作基类的类不支持复制和赋值(可能通过虚clone()
函数除外).
关于开销:相比什么?调用虚函数通常比调用非虚函数更昂贵.但是如果你正在使用虚函数,那是因为你需要运行时调度; 使用其他机制模拟这可能会更加昂贵.
是的,正如其他人所说,您基本上使用带有纯虚拟(抽象)成员函数且没有数据成员的类。实现这个接口的时候,自然要提供这些方法。
另一方面,这与动态分配无关。无论您拥有自动对象(即堆栈)还是动态对象(即堆),都与您如何使用它们(包括多态性)无关。你的意思是动态绑定吗?
现在,说了这么多,您可以在不使用模板的动态绑定(即“多态性”)的情况下实现接口。基本上,您可以使用 SFINAE+CRTP 通过从模板类私有继承来检查给定的成员函数是否存在。基本上,您的父类(不包含虚拟成员)template <typename T> class FooIface;
(继承自 as )将通过尝试调用它来class Foo : private FooIface<Foo>
确保T
具有成员函数。foo
使用元编程技巧,您还可以确保foo
具有正确的类型。
但这可能太麻烦并且太难阅读。抽象基类是常见的方法。