2008-12-13 8 views
3

pourquoi cela se produit-il?Intéressant C++ Résumé Fonction

Lorsque u créer classe abstraite en C++ Ex: classe A (qui a une fonction virtuelle pure) après que classe B est héritée de la classe A

Et si classe A a constructeur appelé A() suppose que je créé un objet de classe B le compilateur initialise la classe de base première à savoir classe A puis initialiser le classe B Alors .......? La première chose est que nous ne pouvons pas accéder à un constructeur de n'importe quelle classe sans un objet puis comment il initialise le constructeur de la classe abstraite si nous ne pouvons pas créer un objet de classe abstraite.

Répondre

8

Réponse rapide: Les constructeurs sont spéciaux. Lorsque le constructeur de A est toujours en cours d'exécution, alors l'objet en construction n'est pas encore réellement de type A. Il est toujours en cours de construction. Lorsque le constructeur se termine, c'est maintenant un A.

Il en est de même pour le dérivé B. Le constructeur de A s'exécute en premier. Maintenant, c'est un A. Ensuite, le constructeur de B commence à fonctionner. Pendant ce temps, l'objet est toujours réellement un A. Seulement quand le constructeur de B finit il devient un B.

Vous pouvez le vérifier en essayant d'appeler la fonction virtuelle pure à partir des constructeurs. Si la fonction est définie dans A et que le constructeur de B l'appelle, il y aura une erreur d'exécution au lieu d'exécuter le remplacement de B, car l'objet n'est pas encore de type B.

Le compilateur ne vous permettra pas de générer du code qui construira un A, en raison de la fonction virtuelle pure. Mais il va générer du code pour construire un A dans le cadre du processus de construction d'un B. Il n'y a pas de magie impliquée dans cela. La règle selon laquelle vous ne pouvez pas construire un A est imposée par les règles de langage, pas par la physique. La langue soulève cette règle dans le cas particulier de la construction d'objets de B.

+0

Après avoir essayé d'appeler la méthode virtuelle depuis le constructeur et avoir vu le résultat, rappelez-vous toujours de ne pas appeler les méthodes virtuelles dans les constructeurs :) –

+0

Puis oubliez cette règle dans C++/CLI où elle ne s'applique pas! –

4

class A est abstraite mais class B ne l'est pas. Afin de construire class B, il doit implémenter toutes les fonctions de membre virtuel pur de class A.

class A 
{ 
public: 
    A() {} 
    virtual ~A() {} 
    virtual void foo() = 0; // pure virtual 
    int i; 
}; 


class B : public A 
{ 
public: 
    B() {} 
    virtual ~B() {} 
    virtual void foo() {} 
    int j; 
}; 

La Une mise en page de classe pourrait être quelque chose comme ceci:

 
+---------+  +---------+ 
| vftable | --> | ~A() | --> address of A::~A() 
+---------+  +---------+ 
| i  |  | foo() | --> NULL, pure virtual 
+---------+  +---------+ 

La mise en page de classe B pourrait être quelque chose comme ceci:

 
+---------+  +---------+ 
| vftable | --> | ~B() | --> address of B::~B() 
+---------+  +---------+ 
| i  |  | foo() | --> address of B::foo() 
+---------+  +---------+ 
| j  | 
+---------+ 
+0

Merci pour la réponse mais je veux savoir comment il crée l'objet interne de la classe abstraite ?????? –

+0

Ridiculement sur une réponse élaborée à une question simple. –

+0

Peut-être, j'ai fait une réponse simple en premier, mais cela n'a pas répondu à la question de Darshan. – dalle

1
struct A { 
    A(int x) {..} 
    virtual void do() = 0; 
}; 

struct B : public A { 
    B() : A(13) {}  // <--- there you see how we give params to A c'tor 
    virtual void do() {..} 
}; 
0
And if class A has constructor called A() suppose i created an 
Object of class B then the compiler initializes the base class 
first i.e.class A and then initialize the class B 
Then.......? 

En fait, vous l'avez dans le mauvais sens:

Lorsque vous créez un objet de classe B le constructeur de B est appelé.
Si vous ne spécifiez pas comment le constructeur B appelle un constructeur alors le compilateur insère automatiquement la première action dans la liste initialiseur un appel au constructeur par défaut de A.

Si vous ne souhaitez pas utiliser la valeur par défaut constructeur, vous devez explicitement mettre l'appel au constructeur A approprié comme premier élément dans la liste d'initialisation. Lorsque la construction de A est terminée, la construction de B se poursuit.

First thing is we can not access a constructor of any class without an Object 
then how it is initialize the constructor of abstract class if we can not create 
an object of abstract class . 

Vous dictez ce qui précède comme si vous considériez A et B des choses différentes. Un objet de classe B est aussi un objet de classe A. C'est l'objet dans son ensemble qui est valide. L'objet entier est de classe B mais il contient (en tant que partie du même objet) toutes les informations provenant de la classe A.

0

Le fait de ne pas pouvoir instancier la classe A ne signifie pas qu'il est impossible d'instancier la classe A. Vous n'êtes pas autorisé à instancier A car le compilateur sait que A est abstrait et rejette tout code que vous écrivez qui tente d'instancier directement A. Il interdit le code comme ceci:

A a; 
new A(); 

Ce qui fait un résumé de la classe est qu'il a des méthodes virtuelles pures. Cependant, rien n'empêche intrinsèquement une telle classe d'être instanciée. La norme C++ dit simplement que ce n'est pas autorisé. Le compilateur est parfaitement capable de générer des instructions pour instancier une classe abstraite. Tout ce qu'il a à faire est de réserver la bonne quantité de mémoire, puis d'appeler le constructeur, comme pour une classe non-abstraite.

Lorsque vous instanciez B, toute la mémoire de la classe est allouée à la fois. Puisque tous les octets sont là, il y a essentiellement une instance A, prête à être initialisée par le constructeur. (Mais notez que la mémoire n'est pas formellement considérée comme un objet de type A jusqu'à après le constructeur A a terminé son exécution.) Le constructeur A s'exécute, puis le constructeur B s'exécute.