为什么在C ++中没有基类?

快速的问题:从devise的angular度来看,为什么在C ++中,没有母类的基类,通常在其他语言中是什么object呢?

Stroustrup的常见问题可以find最终的裁决。 总之,它没有传达任何语义。 这将有一个成本。 模板对容器更有用。

为什么C ++没有一个通用的类对象?

  • 我们不需要:大多数情况下,通用编程提供了静态types的安全select。 其他情况下使用多重inheritance进行处理。

  • 没有有用的普遍类:一个真正的普遍不携带它自己的语义。

  • 一个“普遍”的类鼓励对types和接口的粗略思考,导致运行时间过长的检查。

  • 使用通用基类意味着成本:对象必须被堆分配为多态; 这意味着内存和访问成本。 堆对象自然不支持复制语义。 堆对象不支持简单的作用域行为(这会使资源pipe理变得复杂)。 通用基类鼓励使用dynamic_cast和其他运行时检查。

首先考虑一下为什么你想要有一个基础class。 我可以想到几个不同的原因:

  1. 支持可用于任何types对象的generics操作或集合。
  2. 包含所有对象通用的各种过程(如内存pipe理)。
  3. 一切都是一个对象(没有原始的!)。 一些语言(如Objective-C)没有这个,这使得事情非常混乱。

这些是Smalltalk,Ruby和Objective-C语言的语言都具有基类的两个很好的理由(从技术上来说,Objective-C并没有真正的基类,只是出于所有的目的和目的)。

对于#1,需要在单一接口下统一所有对象的基类,这是通过在C ++中包含模板来消除的。 例如:

 void somethingGeneric(Base); Derived object; somethingGeneric(object); 

是不必要的,当你可以通过参数多态来一直维持types完整性的时候!

 template <class T> void somethingGeneric(T); Derived object; somethingGeneric(object); 

对于#2,而在Objective-C中,内存pipe理过程是类实现的一部分,并且是从基类inheritance的,C ++中的内存pipe理是使用组合而不是inheritance来执行的。 例如,你可以定义一个智能指针包装器,它将对任何types的对象执行引用计数:

 template <class T> struct refcounted { refcounted(T* object) : _object(object), _count(0) {} T* operator->() { return _object; } operator T*() { return _object; } void retain() { ++_count; } void release() { if (--_count == 0) { delete _object; } } private: T* _object; int _count; }; 

然后,而不是调用对象本身的方法,你会在它的包装器中调用方法。 这不仅允许更通用的编程:它还可以让你分开关注(理想情况下,你的对象应该更关心它应该做什么,而不是在不同情况下如何pipe理它的内存)。

最后,用C ++这样的原语和实际对象的语言,丢失了基类(对每个值都有一个一致的接口)的好处,因为那样你就有了某些不符合这个接口的值。 为了在这种情况下使用原语,你需要把它们放到对象中(如果你的编译器不会自动的)。 这造成了很多复杂性。

所以,对你的问题的简短回答:C ++没有基类,因为通过模板有参数多态性,它不需要。

C ++variables的主要范式是按值传递,而不是通过引用。 强制所有从一个根Object派生的东西都会使得它们被值传递给一个事实上的错误。

(因为接受一个对象的值作为参数,将定义切片,并删除它的灵魂)。

这是不受欢迎的。 C ++让你思考你是否想要价值或引用语义,给你select。 这是性能计算中的一件大事。

问题是在C ++中有这样的types! 这是void 。 :-)任何指针都可以安全地隐式转换为void * ,包括指向基本types的指针,没有虚拟表的类以及具有虚拟表的类。

由于它应该与所有这些类别的对象兼容,因此void本身不能包含虚拟方法。 如果没有虚函数和RTTI,没有有用的关于types的信息可以从void (它与EVERYtypes匹配,所以只能告诉每个types都是真的),但是虚函数和RTTI会使简单types非常无效,并停止C ++作为一种适用于低级别直接存储器访问编程的语言

所以有这样的types。 由于语言的低级特性,它只提供非常简约的(实际上是空的)接口。 🙂

C ++是一种强types语言。 然而令人费解的是,在模板专业化的背景下,它没有一个通用的对象types。

以例如模式为例

 template <class T> class Hook; template <class ReturnType, class ... ArgTypes> class Hook<ReturnType (ArgTypes...)> { ... ReturnType operator () (ArgTypes... args) { ... } }; 

可以实例化为

 Hook<decltype(some_function)> ...; 

现在让我们假设我们想要一个特定的function相同。 喜欢

 template <auto fallback> class Hook; template <auto fallback, class ReturnType, class ... ArgTypes> class Hook<ReturnType fallback(ArgTypes...)> { ... ReturnType operator () (ArgTypes... args) { ... } }; 

与专门的实例

 Hook<some_function> ... 

但是,可惜的是,即使T类在专业化之前可以代表任何types(类或不类),也没有等价的auto fallback (在这种情况下,我使用的语法是最明显的通用非types语法)对于专门化之前的任何非types模板参数。

所以通常这个模式不会从types模板parameter passing到非types模板参数。

就像C ++语言中的许多angular落一样,答案可能是“没有委员会成员想到”。

C ++最初被称为“带类的C”。 它是C语言的进步,不像其他一些更现代的东西,如C#。 你不能把C ++看作是一门语言,而是作为语言的基础(是的,我记得斯科特·迈耶斯的着作Effective C ++)。

C本身是一种混合的语言,C语言和它的预处理器。

C ++增加了另一个组合:

  • 类/对象方法

  • 模板

  • STL

我个人不喜欢一些直接从C到C ++的东西。 一个例子是枚举function。 C#允许开发人员使用它的方式更好:它限制枚举在它自己的范围内,它有一个Count属性,它很容易迭代。

由于C ++想要与C进行逆向兼容,devise者非常容许允许C语言将其整体input到C ++中(这里有一些细微的差别,但是我不记得使用C编译器可以做什么无法使用C ++编译器)。