aspects techniques de 'isa' en C ++
-
27-09-2019 - |
Question
Je compris que ce que cela signifie exactement de technical point of view
, cela signifie que mon derived class
peut toujours être converti en base class
, c'est-il? Je lis des documents sans aucune référence à des aspects techniques, que la philosophie! merci à l'avance
La solution
cela signifie que ma classe dérivée peut toujours être converti en classe de base
En fait, cela signifie mieux que cela. int
peut toujours être converti en float
, mais cela ne signifie pas un int « est un » flottant. Cela signifie simplement un flotteur peut être construit à partir d'un int. De même, vous pouvez avoir des classes définies par l'utilisateur qui convertissent, mais ont pas d'autre relation.
Avec l'héritage, un pointeur ou une référence à la classe dérivée peut toujours être converti en un pointeur ou une référence à la classe de base [*]. C'est-à-dire un objet de la classe dérivée peut tenir en place d'un objet de la classe de base. Il est en fait une de ces choses. Si une personne peut se substituer à un chirurgien du cerveau, alors ils sont un chirurgien du cerveau.
Une définition formelle si "est un" est de Barbara Liskov . Ce qui est certes encore la philosophie, mais il est la philosophie très solide et il se rapporte directement à la façon dont vous écrivez des programmes.
L'autre chose que vous devez continuer tout droit lorsque vous utilisez l'héritage en C ++ est la différence entre le polymorphisme d'exécution (réalisé en utilisant des fonctions de virtual
) et polymorphisme statique (qui ne nécessite pas réellement l'héritage du tout). Avec les appels de fonction non virtuelle, la version de la fonction appelée est toujours la version définie dans la classe que le compilateur est dit que l'objet a (type statique). Cela pourrait ne pas fonctionner correctement en fait, si elle est surchargée dans la classe dérivée. Avec des appels virtuels, la version appelée la version définie dans la classe de l'objet est en fait (le type de dynamique). Il est essentiel de décider lequel des deux types de « est un » que vous visez.
[*] et l'objet soit valablement accessible par le pointeur, qui est. Vous pouvez toujours forcer les types de pointeur avec reinterpret_cast
, mais ce n'est pas ce que je veux dire ici. Et il y a quelques détails fiddly - si la classe de base est ambigu alors vous ne pouvez convertir le pointeur en une seule fois, mais vous pouvez le faire en utilisant explicitement plusieurs moulages sans ambiguïté. Si la classe de base n'est pas accessible, alors vous peut convertir, mais seulement avec un casting de style C, pas implicitement. Le casting de style C agit comme un static_cast
qui ignore l'accessibilité, pas comme un reinterpret_class
. Ainsi, vous obtenez un pointeur de travail, mais nous espérons aussi un fort sentiment que vous faites quelque chose de très mal; -)
Autres conseils
Une classe dérivée peut être convertie en une seule classe de base accessible et sans ambiguïté à un moment donné R. Il ne manque pas de références et quel autre endroit que le standard C ++ lui-même.
10.2 $ est une bonne référence: Un dérivé classe peut se servir de classe de base sous réserve de contrôle d'accès; voir 11.2. UNE pointeur vers une classe dérivée peut être converti implicitement à un pointeur vers une classe de base non ambiguë accessible (4.10). Une lvalue d'une classe dérivée type peut être lié à une référence à un classe de base non ambiguë accessible (8.5.3). -end ndlr]
Et encore
10,3 $ - « La base spécificateur liste spécifie le type de la classe de base sous-objets contenus dans un objet de le type de classe dérivée. [..] Ici, un objet de la classe Derived2 aura un subobject de classe dérivée qui tour aura une classe de sous-objet Base. [...]
En termes de principes OOAD:
Je recommande personnellement articles de Robert Martin pour obtenir une bonne tenue sur ce notamment le principe de l'OCP . Il est impossible pour moi de battre la clarté et de l'autorité avec laquelle l'auteur explique ces directives légendaires OOAD
Regardez aussi LSP comme expliqué dans le poste de @Steves