Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我想虚拟多少?_C++_Virtual - Fatal编程技术网

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++“接口”是坏的接口,因为它们在编译时不会抱怨…如果不使用虚拟,则在子类中不重写,而是隐藏。如果强制转换为父类型,那么对这些隐藏方法的调用将调用父方法而不是子方法。我无法预见我自己的应用程序在短期内需要运行时多态性,但我可以想象我的库会有非常合法的用途。性能受到的影响有多大?取决于用例,但是它们并不比常规函数调用慢多少。可能只是几次行动。