2013-10-17 3 views
6

Tenir compte du programme suivantPourquoi pA, pB, pC ne sont-ils pas égaux?

#include<iostream> 
using namespace std; 
class ClassA 
{ 
public: 
    virtual ~ClassA(){}; 
    virtual void FunctionA(){}; 

}; 

class ClassB 
{ 
public: 
    virtual void FunctionB(){}; 
}; 



class ClassC : public ClassA,public ClassB 
{ 

}; 

void main() 
{ 
    ClassC aObject; 
    ClassA* pA = &aObject; 
    ClassB* pB = &aObject; 
    ClassC* pC = &aObject; 

    cout<<"pA = "<<pA<<endl; 
    cout<<"pB = "<<pB<<endl; 
    cout<<"pC = "<<pC<<endl; 

} 

pA, pB, pC sont supposés égaux, mais le résultat est

pA = 0031FD90

pB = 0031FD94

pC = 0031FD90

wh y pB = pA + 4? et quand je change

class ClassA 
{ 
public: 
    virtual ~ClassA(){}; 
    virtual void FunctionA(){}; 

}; 
class ClassB 
{ 
public: 
    virtual void FunctionB(){}; 
}; 

à

class ClassA 
{ 
}; 

class ClassB 
{ 
}; 

le résultat est

pA = 0030FAA3

pB = 0030FAA4

pC = 0030FAA3

pB = pA + 1?

+0

je pense que cela vous aidera, http://stackoverflow.com/questions/254673/multiple-inheritance-from-two-derived-classes – shankar

Répondre

1

L'objet à multiplication héritée possède deux sous-objets fusionnés. Je devrais deviner le compilateur pointe l'un des pointeurs vers un objet interne.

0

C a deux sous-objets hérités, donc la concaténation d'un objet A et d'un objet B. Lorsque vous avez un objet C, il est composé d'un objet A suivi d'un objet B. Ils ne se trouvent pas à la même adresse, c'est pourquoi. Les trois pointeurs pointent vers le même objet, mais comme des superclasses différentes. Le compilateur fait le changement pour vous, donc vous n'avez pas à vous en préoccuper.

maintenant. Pourquoi y a-t-il une différence de 4 dans un cas et de 1 dans un autre? Eh bien, dans le premier cas, vous avez des fonctions virtuelles pour A et B, donc chaque sous-objet doit avoir un pointeur sur son vtable (la table contenant les adresses des appels de fonctions virtuelles résolues). Donc, dans ce cas, sizeof(A) est 4. Dans le second cas, vous n'avez pas de fonctions virtuelles, donc pas de vtable. Mais chaque sous-objet doit être adressable indépendamment, donc le compilateur doit toujours allouer une adresse différente pour le sous-objet de classe A et le sous-objet de classe B. Le minimum de différence entre deux adresses est 1. Mais je me demande si EBO optimisation) n'aurait pas dû être lancé dans ce cas.

+0

a probablement à voir avec aucune optimisation spécifiée au moment de la compilation. – Raja

0

C'est le détail de l'implémentation du compilateur. La raison pour laquelle vous avez atteint ce cas est que vous avez MI dans votre code. Pensez à la manière dont l'ordinateur accède au membre ClassB, en utilisant le décalage pour accéder au membre. Disons que vous avez deux int dans la classe B, en utilisant l'instruction suivante pour accéder au second membre int.

*((int*)pb + 1) // this actually will be assembly generate by compiler 

Mais si le point pb au début de la aObject dans votre classe, cela ne fonctionnera pas plus, donc le compilateur besoin de générer de versions multiples d'assemblage pour accéder à la même base de membres sur la structure Hériter de la classe, et avoir un coût d'exécution.

C'est pourquoi le compilateur ajuste le pb non égal à pa, ce qui fera fonctionner le code ci-dessus, c'est le moyen le plus simple et le plus efficace pour l'implémenter.

Et c'est aussi expliquer pourquoi pa == pc mais pas égal à pb.

Questions connexes