Petite question: à partir d'une conception de point de vue, pourquoi est-ce, en C++, il n'y a pas de mère-à-tout de la classe de base, ce qui est habituellement object
dans d'autres langues?
Réponses
Trop de publicités?La décision définitive est trouvé ici. En bref, il ne rend pas toute signification sémantique. Il y aura un coût. Les modèles sont de plus en plus utile pour les conteneurs.
Pourquoi ne pas en C++ universelle Objet de classe?
Nous n'avons pas besoin d'un: programmation générique fournit de manière statique type de solutions de rechange sans danger dans la plupart des cas. D'autres cas sont traités à l'aide de l'héritage multiple.
Il n'est pas utile de classe universelle: un véritablement universelle porte pas de sémantique qui lui est propre.
Un "universel" de la classe encourage bâclée réflexion sur les types et les interfaces et conduit à un excès d'exécution de la vérification.
À l'aide d'un universel de la classe de base implique des coûts: les Objets doivent être allouées sur la pile pour être polymorphe; ce qui implique, de la mémoire et de coût d'accès. Tas d'objets n'est pas naturellement en charge sémantique de copie. Tas d'objets ne supportent pas la simple étendue de comportement (ce qui complique la gestion des ressources). Un universel de la classe de base encourage l'utilisation de dynamic_cast et d'autres au moment de l'exécution de la vérification.
Nous allons d'abord penser à pourquoi vous voulez disposer d'une base de classe à la première place. Je ne peux penser à quelques différentes raisons:
- À l'appui de générique d'opérations ou de collections qui vont travailler sur des objets de tout type.
- Diverses procédures qui sont communes à tous les objets (tels que la gestion de la mémoire).
- Tout est un objet (pas de primitives!). Certaines langues (comme Objective-C) ne l'avez pas, ce qui rend les choses assez salissante.
Ce sont deux bonnes raisons que les langues de la Causerie, de Rubis et d'Objective-C de la marque ont de la base de classes (techniquement, Objective-C n'ont pas vraiment de la classe de base, mais pour toutes fins utiles, il n').
Pour le #1, la nécessité d'une classe de base qui unifie tous les objets sous une interface unique est suspendue par l'inclusion de templates en C++. Par exemple:
void somethingGeneric(Base);
Derived object;
somethingGeneric(object);
est inutile, quand vous pouvez maintenir le type de l'intégrité de tout le chemin par le biais de polymorphisme paramétrique!
template <class T>
void somethingGeneric(T);
Derived object;
somethingGeneric(object);
Pour le #2, alors qu'en Objective-C, la gestion de la mémoire procédures font partie d'une classe de mise en œuvre, et sont héritées de la classe de base, la gestion de la mémoire en C++ est réalisée à l'aide de la composition plutôt que de l'héritage. Par exemple, vous pouvez définir un pointeur intelligent wrapper qui va effectuer le comptage de références sur des objets de tout type:
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;
};
Alors, au lieu d'appeler des méthodes sur l'objet lui-même, vous seriez de l'appel de méthodes dans son emballage. Cela permet non seulement de plus de programmation générique: il vous permet aussi de séparer les préoccupations (depuis idéalement, votre objet doit être plus préoccupés par ce qu'il doit faire, que de la façon dont sa mémoire doivent être gérés dans des situations différentes).
Enfin, dans un langage à la fois primitives et des objets comme C++, les avantages d'avoir une classe de base (une interface cohérente pour chaque valeur) sont perdus, depuis lors, vous avez certaines des valeurs qui ne correspondent pas à cette interface. Afin d'utiliser les primitives dans ce genre de situation, vous avez besoin de les soulever en les objets (si votre compilateur ne pas le faire automatiquement). Cela crée beaucoup de complication.
Donc, la réponse courte à votre question: C++ n'est pas une classe de base, parce que, ayant polymorphisme paramétrique à l'aide de modèles, il n'est pas nécessaire.
Le paradigme dominant pour C++ variables est passé par valeur, de ne pas passer par-réf. Obliger tout pour être dérivée à partir d'une racine Object
rendrait leur passage par valeur une erreur ipse facto.
(En raison de l'acceptation d'un Objet par valeur comme paramètre, par définition, coupez-le en tranches et retirez son âme).
Cela est regrettable. C++ qui vous fait penser que si tu voulais de la valeur de référence ou de la sémantique, de vous donner le choix. C'est une chose importante dans les performances de calcul.
Le problème est qu'il existe aussi un type en C++! C'est - void
. :-) Un pointeur peut être en toute sécurité implicitement convertie en void *
, y compris les pointeurs de types de base, les classes sans table virtuelle et les classes avec table virtuelle.
Depuis elle devrait être compatible avec toutes les catégories d'objets, void
lui-même ne peut pas contenir des méthodes virtuelles. Sans fonctions virtuelles et le RTTI, pas d'informations utiles sur le type peut être obtenu à partir d' void
(elle correspond à TOUS les types, de sorte que pouvez dire des choses qui sont vraies pour TOUT type), mais les fonctions virtuelles et le RTTI ferait types simples très inefficace et arrêter le C++ étant un langage adapté à la programmation de bas niveau avec accès direct à la mémoire etc.
Si, il est ce type. Il fournit simplement très minimaliste (en fait, vide) de l'interface en raison du faible niveau de la nature de la langue. :-)
C++ a d'abord été appelé "C with classes". C'est une progression du langage C, à la différence de certains autres plus modernes comme le C#. Et vous ne pouvez pas voir le C++ comme langage, mais en tant que fondement de langues (Oui, je pense à la Scott Meyers livre Effective C++).
C est lui-même un mélange de langues, le langage de programmation C et son préprocesseur.
C++ ajoute un autre mélange:
de la classe, les objets de l'approche
modèles
la STL
Personnellement, je n'aime pas certaines choses qui viennent directement de C à C++. Un exemple est l'enum fonctionnalité. La façon dont C# permet au développeur d'utiliser c'est mieux: elle limite l'enum dans son propre champ d'application, il a une propriété Count et il est facilement itératif.
Comme C++ voulais être retrocompatible avec C, le designer a été très permissive pour permettre le langage C pour entrer dans son ensemble à C++ (il y a quelques différences subtiles, mais je ne me souviens pas de quelque chose que vous pouvez faire à l'aide d'un compilateur C que vous ne pouviez pas faire à l'aide d'un compilateur C++).