继承及;虚拟函数与泛型编程 我需要理解,C++中是否真的存在“代码>继承和虚函数< /代码>,并且可以使用泛型编程< /COD>实现一切。这是源于 Alexander Stepanov ,我看的是 < P>这似乎是一个很学术的问题,就像生活中的大多数事情有很多方法去做事情一样,在C++的情况下,你有很多解决问题的方法。不需要对事物采取异或态度。

继承及;虚拟函数与泛型编程 我需要理解,C++中是否真的存在“代码>继承和虚函数< /代码>,并且可以使用泛型编程< /COD>实现一切。这是源于 Alexander Stepanov ,我看的是 < P>这似乎是一个很学术的问题,就像生活中的大多数事情有很多方法去做事情一样,在C++的情况下,你有很多解决问题的方法。不需要对事物采取异或态度。,c++,stl,generic-programming,C++,Stl,Generic Programming,多态性(即动态绑定)对于基于运行时数据的决策至关重要。通用数据结构很好,但它们是有限的 示例:考虑一个离散事件仿真器的事件处理程序:用纯虚函数实现这一点非常便宜,但是如果纯粹是用模板类完成的话,它是冗长的,非常不灵活的。 根据经验法则:如果您发现自己正在切换(或者正在切换)某个输入对象的值,并根据其值执行不同的操作,那么可能存在一个更好的(在可维护性方面)动态绑定解决方案 不久前,我想了一个类似的问题,我只能梦想着给你一个我收到的这么好的答案。也许这是有帮助的:它们有不同的用途。泛型编程(至少在

多态性(即动态绑定)对于基于运行时数据的决策至关重要。通用数据结构很好,但它们是有限的

示例:考虑一个离散事件仿真器的事件处理程序:用纯虚函数实现这一点非常便宜,但是如果纯粹是用模板类完成的话,它是冗长的,非常不灵活的。 根据经验法则:如果您发现自己正在切换(或者正在切换)某个输入对象的值,并根据其值执行不同的操作,那么可能存在一个更好的(在可维护性方面)动态绑定解决方案


不久前,我想了一个类似的问题,我只能梦想着给你一个我收到的这么好的答案。也许这是有帮助的:

它们有不同的用途。泛型编程(至少在C++中)是关于编译时多态性的,而虚拟函数是关于运行时多态性的


如果具体类型的选择取决于用户的输入,那么您确实需要运行时多态性-模板对您没有帮助。

我总是喜欢将模板和继承看作两个正交的概念,从字面意义上讲:对我来说,继承是“垂直的”,从顶部的基类开始,到“向下的”到越来越多的派生类。每个(公开的)派生类在其接口方面都是基类:狮子狗是狗是动物

另一方面,模板是“水平”的:模板的每个实例都有相同的正式代码内容,但两个不同的实例是完全独立的、不相关的部分,它们“并行”运行,彼此看不见。对整数数组进行排序在形式上与对浮点数组进行排序相同,但整数数组与浮点数组根本不相关

因为这两个概念是完全正交的,所以它们的应用也是完全正交的。当然,您可以设计一种情况,在这种情况下,您可以用另一种替换另一种,但如果按照惯用方式进行,模板(通用)编程和继承(多态)编程都是独立的技术,它们都有自己的位置


继承是通过添加细节使抽象概念越来越具体。泛型编程本质上是代码生成

作为我最喜欢的例子,让我提到这两种技术如何在一个流行的类型擦除实现中完美地结合在一起:一个处理程序类持有一个指向抽象容器类基的私有多态指针,而具体的派生容器类被确定为一个模板化类型推断构造函数。我们使用模板代码生成来创建任意的派生类族:

// internal helper base
class TEBase { /* ... */ };

// internal helper derived TEMPLATE class (unbounded family!)
template <typename T> class TEImpl : public TEBase { /* ... */ }

// single public interface class
class TE
{
  TEBase * impl;
public:
  // "infinitely many" constructors:
  template <typename T> TE(const T & x) : impl(new TEImpl<T>(x)) { }
  // ...
};
//内部助手库
类TEBase{/*…*/};
//内部辅助对象派生的模板类(无界族!)
模板类TEImpl:public TEBase{/*…*/}
//单一公共接口类
TE类
{
TEBase*impl;
公众:
//“无限多”构造函数:
模板TE(const T&x):impl(new TEImpl(x)){
// ...
};

在理想情况下,您可以使用静态多态性模板,以便在类型不由用户输入确定的情况下提供最佳性能

事实上,模板会将大部分代码强制放入头中,这会导致编译时间爆炸

我已经完成了一些利用静态多态性实现通用RPC库的大型通用编程(https://github.com/bytemaster/mace (rpc_静态_多边形分支))。在本例中,协议(JSON-RPC、传输(TCP/UDP/Stream/etc)和类型)在编译时都是已知的,因此没有理由执行vtable分派。。。还是有

当我通过一个.cpp的预处理器运行代码时,它会产生250000行代码,编译一个对象文件需要30秒以上的时间。我在Java和C#中实现了“完全相同”的功能,它在大约一秒钟内编译完成

几乎您包含的每个stl或boost头都会添加数千行或10行的代码,这些代码必须在每个对象文件中进行处理,其中大部分是冗余的

编译时间重要吗?在大多数情况下,它们对最终产品的影响比“最大化优化vtable消除”更为显著。原因是每个“bug”都需要一个“尝试修复、编译、测试”的周期,如果每个周期都需要30秒以上的时间,那么开发就会慢到爬行(请注意Google go语言的动机)

在用java和C++语言工作了几天之后,我决定我需要重新思考我的C++方法。没有理由C++程序编译得比实现相同函数的底层C要慢得多。p> 我现在选择运行时多态性,除非分析显示瓶颈在vtable分派中。我现在使用模板在处理“void*”或抽象基类的底层对象之上提供“即时”多态性和类型安全接口。通过这种方式,用户不需要从我的“接口”派生,并且仍然具有泛型编程的“感觉”,但他们可以从快速编译中获益。如果性能成为一个问题,那么可以用静态多态性替换通用代码

结果是惊人的,编译时间从30秒以上下降到了大约1秒。后预处理器源代码现在是几千行,而不是250行