C++ 我想虚拟多少?
我正在编写一个抽象的超类,其中每个方法都将被重写。我可以实现一些默认功能,但大多数情况下,将实现留给子类编写器就足够了 既然几乎每个方法都将被覆盖,那么我应该将多少虚拟方法和多少常规方法保留下来?在当前的版本中,一切都是虚拟的,但我仍然没有让任何人使用,因此设计是灵活的C++ 我想虚拟多少?,c++,virtual,C++,Virtual,我正在编写一个抽象的超类,其中每个方法都将被重写。我可以实现一些默认功能,但大多数情况下,将实现留给子类编写器就足够了 既然几乎每个方法都将被覆盖,那么我应该将多少虚拟方法和多少常规方法保留下来?在当前的版本中,一切都是虚拟的,但我仍然没有让任何人使用,因此设计是灵活的 虚拟功能有哪些优点/缺点?链接到有关这方面的好阅读材料将不胜感激 如果要覆盖所有内容,为什么不将其作为一个接口来实现呢?虚拟函数调用比非虚拟函数调用慢,但是如果需要运行时多态性,就别无选择。不管有多少个虚拟函数调用,其开销大体上
虚拟功能有哪些优点/缺点?链接到有关这方面的好阅读材料将不胜感激 如果要覆盖所有内容,为什么不将其作为一个接口来实现呢?虚拟函数调用比非虚拟函数调用慢,但是如果需要运行时多态性,就别无选择。不管有多少个虚拟函数调用,其开销大体上是恒定的,所以没有什么缺点。您可以看到许多专业类的设计,如IDirect3D9Device,在一个类中有许多虚拟方法。任何您想要覆盖的方法都应该声明为虚拟的 虚拟方法的优点是在这种情况下:
BaseClass * o = new SubClass;
o->MyVirtualMethod();
。。。将调用的是子类::MyVirtualMethod()(如果子类定义了MyVirtualMethod,这通常是您想要的)。如果该方法是非虚拟的,则将调用BaseClass::MyVirtualMethod(),因为指针(o)的类型为BaseClass
虚拟方法的缺点是,与非虚拟方法相比,调用虚拟方法的成本稍微高一些(就使用的CPU周期而言)。答案已经是你的开场白的一部分-你已经说过,每个方法都将被覆盖。只需将所有应重写的函数设置为虚拟函数,其余函数保持为非虚拟函数。这就是所谓的虚拟函数,它没有任何问题,事实上,这通常是一个好主意 使用virtual意味着能够使用只有抽象类类型的派生类代码。
如果您手头总是有对象的确切类型,那么您不需要虚拟对象,而且您的抽象类也毫无用处。
如果要通过抽象使用对象&。使用虚拟功能成员。
你可能想读书
(……当标准C++中存在接口时)< /P>
如果您真的想要界面:使用尽可能少的虚拟方法来完成任务。尝试考虑聚合对继承的影响。
虚函数让你在基类指针上调用一个方法,得到正确的类的行为,而不知道对象是基类还是派生类。这就是虚拟功能的“优势”,尽管它是虚拟功能的本质,也是虚拟功能设计的目的
因此,从类的设计和预期用途来看,您是否需要这个特性应该是显而易见的。这不应该是一个“嗯,什么是折衷”的问题,而是“没有虚拟功能,实现将是一个复杂的混乱。”考虑到这一点,虚拟函数有运行时成本,但这永远不应该成为决定是否使用它们的一个因素;与优势相比,成本微不足道。相反,在C++中有非虚函数的选项是这样的,这样,如果你知道你不需要它们,你就没有那么小的开销。在Java中,所有函数都是虚拟的;没有选择就没有它,推理是即使你不需要它,无论如何,它也比任何语言中的运行时开销都要付出代价。如果C++有接口,这将是一个很好的建议。OP确实提到基类实现了一些基本功能。根据目标编译器的不同,接口不能作为本机选项使用。例如,在Borland C++ Builder 6中,接口通过使用简单的定义映射到抽象类。仅仅因为没有正式的语言特性叫做“接口”,这并不能使这个问题成为一个坏的答案。泛型术语“接口”当然适用于抽象的基类,它只包含纯虚函数。嗯,不是严格的接口,而是定义抽象超类的头文件。实际上这是一个非常好的想法,但是C++在这一点上是令人失望的。强制派生类实现功能的一种“简单”方法是使用派生类的确切类型E来模板化抽象类,然后在基类构造函数中对E进行伪方法调用。看看Bil,如果你想了解更多的东西,“界面”在语言开始在正式的特征中被称为“接口”之前有一个一般的含义。我不明白为什么人们会如此热衷于引用抽象的基类,而C++中的纯虚拟函数只是“接口”,你是对的。但是“简单地使用接口!!!:)”在这里仍然是一个错误的答案。此外,C++“接口”是坏的接口,因为它们在编译时不会抱怨…如果不使用虚拟,则在子类中不重写,而是隐藏。如果强制转换为父类型,那么对这些隐藏方法的调用将调用父方法而不是子方法。我无法预见我自己的应用程序在短期内需要运行时多态性,但我可以想象我的库会有非常合法的用途。性能受到的影响有多大?取决于用例,但是它们并不比常规函数调用慢多少。可能只是几次行动。