简单地说,如何在C++中为单一级别的继承(出于简单和说教的原因)创建接口?我看到了一些没有使用多态性的代码,但是基类包含一个虚拟抽象方法(virtual void TheMethod() = 0)。
现在,使用纯虚拟方法从这个抽象类派生了一个类,但是在随后的代码中,使用派生类的实例时根本没有动态分配。
这样做对吗?由多态设计的使用推断出的开销如何?
我想这是不可能的。这看起来更像是隐藏/幽灵基本方法,即使该方法是一个纯虚拟方法。
稍后编辑:感谢所有设法提供一些好答案的人,我想强调“动态分配”的用法产生的一个关键错误,其意思是强调这种对象创建的可能性是唯一与多态性兼容的。很明显,这不是唯一的方法(但可能是最常见的?)为了利用这种运行时调用行为,但是要进一步澄清我最初的问题:
是否有一种方法可以强迫程序员在不使用纯虚拟方法的情况下实现一个方法?我可能没有理由担心的是,在性能方面是否打开了多态设计的大门(每秒对讨论中的方法进行数千次这样的调用)。
甚至以后的编辑:使基具有一个受保护的构造函数意味着它不能被直接实例化(除了使用工厂或其他友好的方法),这可以解决补偿纯虚拟方法所导致的影响之一。但是,如何确保任何派生类仍然提供自己的方法实现?如果拥有相关vtable的可能夸大的担忧真的不是什么大不了的事情,我将坚持使用纯粹的虚拟方法(因为SFINAE这种奇怪的反复出现的模板模式更难被至少不是中级C++程序员的人阅读和理解--比如我:)。
发布于 2012-08-24 08:35:15
是的,正如其他人所说的那样,您基本上使用了纯虚拟(抽象)成员函数的类,而没有数据成员。在实现此接口时,当然必须提供这些方法。
另一方面,这与动态分配无关。无论您有自动对象(即堆栈)还是动态对象(即堆),都与您如何使用它们无关,包括多形性。你是说动态绑定吗?
现在,说到这一点,您可以实现一个接口,而无需使用与模板的动态绑定(即“多态”)。基本上,您将使用SFINAE+CRTP检查给定成员函数是否存在,方法是私下从模板类继承。基本上,您的父类(它不包含虚拟成员) template <typename T> class FooIface; (继承自as class Foo : private FooIface<Foo>)将通过尝试调用它来确保T具有成员函数foo。使用元编程技巧,您还可以确保foo具有正确的类型。
但这可能太麻烦,也太难读了。抽象基类是常用的方法。
发布于 2012-08-24 08:26:23
您不需要动态分配对象才能在多形性的情况下使用它:
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
}发布于 2012-08-24 08:43:33
出于教学上的原因,如果目标是了解如何在C++中实现多态对象,并测试所创建的类型,则不需要动态分配。然而,在实际的应用程序中,可能会出现这种情况,因为使用多态性的主要原因是在运行时之前不知道具体类型。
请注意,在C++ (以及支持它的几乎所有其他语言中)中,多态性需要引用语义,而不是C++默认使用的值语义。通常,设计用作基类的类将不支持复制和赋值(除了可能通过虚拟clone()函数)。
关于间接费用:与什么相比?调用虚拟函数通常比调用非虚拟函数更昂贵。但是,如果您使用的是虚拟函数,这是因为您需要运行时调度;使用其他机制来模拟这个过程可能会更加昂贵。
https://stackoverflow.com/questions/12105638
复制相似问题