2010-01-28 5 views
1

possible en double:
C++ pointer multi-inheritance fun.plus C++ multiple fun héritage

(Suivi: C++ pointer multi-inheritance fun)

J'écris un code impliquant l'héritage d'un rEF- de base classe de pointeur de comptage; et quelques complexités de C++ ont surgi. Je l'ai réduit comme suit:

Supposons que j'ai:

class A{int x, y;}; 
class B{int xx, yy;}; 
class C: public A, public B {int z;}; 

C c; 
C* pc = &c; 
B* pb = &c; 
A* pa = &c; 

// does pa point to a valid A object? 
// does pb point to a valid B object? 

// does pa == pb ? 

En outre, le fait:

// pc == (C*) pa ? 
// pc == (C*) pb ? 

Merci!

Ici, "==" signifie des points à la même valeur.

+0

La réponse est toujours "pas necsarrily". Qu'est-ce que vous * essayez * vraiment d'accomplir? –

+0

dupliquer: http://stackoverflow.com/questions/2157104/c-pointer-multi-inheritance-fun – Bill

+0

Pas tout à fait un doublon, dans cette question les classes ont des membres donc la réponse est différente. – Skizz

Répondre

3
  • Oui
  • Oui
  • Non
  • Oui
  • Non *

Mais vous devez savoir comment organise C++ mémoire. La disposition d'une classe, cClass, est la suivante:

offset 
0        First base class in list of base classes 
sizeof first base class  Next base class 
sizeof first N-1 base classes Nth base class 
sizeof all base classes  CClass 

OK, il est un peu plus complexe que s'il y a un arbre d'héritage, mais vous devriez obtenir l'idée de base. En supposant un int est de quatre octets puis la classe C est Disposées comme:

offset 
0    A::x 
4    A::y 
8    B::xx 
12   B::yy 
16   C:z 

Mais un objet de type C est tout ce qui précède, si un pointeur vers un C est pointée pour compenser 0. Cependant, C++ permet downcasting implicite, de sorte qu'un pointeur sur un C peut être converti en un pointeur vers un A ou un pointeur vers un B. Mais si vous regardez ce qui précède, un pointeur sur un B est au décalage 8 plutôt que 0 (un pointeur vers un C) et qu'un pointeur vers A est à l'offset 0. Donc, lancer un pointeur vers un C vers un pointeur vers B ajoute 8 à la valeur du pointeur. C'est parce que les méthodes de B supposent que le pointeur 'this' pointe vers le premier membre de B (B :: xx), mais un pointeur vers un C si réinterprété comme un pointeur vers un B (ie la valeur est la même) serait pointeur à une adresse huit octets avant où B est réellement, de sorte que toutes les méthodes de B utiliseraient, dans ce cas, les membres de A.

La projection ascendante (les deux dernières conversions) est différente de celle du poisson. Aller d'un pointeur vers un B vers un pointeur vers un C est vraiment difficile car on ne sait pas si le pointeur vers un B pointe juste vers une instance de B ou vers une instance de C plus huit. C'est là qu'intervient RTTI et la distribution dynamique. Avec les informations RTTI (Run Time Type Information) activées, le pointeur vers B contient des informations supplémentaires qui décrivent réellement ce qu'est B - un simple B ou un B faisant partie d'un C. coût supplémentaire, à la fois le temps d'exécution et l'utilisation de la mémoire. Enfin, cela met en évidence l'ambiguïté de la distribution de style C. Vous devriez vraiment utiliser les distributions de style C++ (static_cast <>, etc) car cela clarifie la façon dont la conversion doit être faite.

* Cela pourrait aussi être un oui, je suppose que cela dépend du compilateur et si RTTI est activé ou désactivé. Vous auriez besoin d'entrer dans les détails de la norme et l'implémentation du compilateur pour dire à coup sûr.