2010-11-30 53 views
3

Comment vérifier si C++ méthode abstraite est définie lors de l'exécutionComment vérifier si la méthode abstraite C de est défini lors de l'exécution

class ABase{ 
public: 
virtual void do1() = 0; 
}; 

class BBase: public ABase{ 
public: 
virtual void do1(){} 
}; 

class CBase: public ABase{ 
public: 
}; 

ABase * base = rand() % 2 ? new BBase() : new CBase(); 
if(&(base->do1) != 0) 
    base->do1(); 

Cela donne une erreur.

Merci, Max

+1

Non. Et quelle serait l'utilité? –

+1

Il n'y a pas de méthode virtuelle ici. Voir ma réponse ci-dessous. –

+0

Bien sûr, cela donne des erreurs - erreurs __compilation__. Ou est-ce que le 'virtuel' manquant juste une typo/pasto, et vous parlez ou __runtime errors__? Ou est-ce des erreurs de compilation __ dans cette comparaison amusante (et fausse)? Si oui, lesquels? Il est impossible de dire avec une telle question bâclée.Je vote pour le clore, car on ne peut raisonnablement répondre à la question. – sbi

Répondre

14

Comme vous ne pouvez pas instancier une classe abstraite, toute classe que vous rencontrez lors de l'exécution seront pas de méthodes virtuelles pures (sauf si vous êtes à la fois dans un constructeur ou destructor), ils auront tous été remplacés par un overrider non-pur. Il n'y a rien à vérifier.

3

CBase est abstrait car il ne surcharge pas ABase :: do1(). Par conséquent, vous ne pouvez pas l'instancier. Ou plutôt, c'est ce qui arriverait si vous aviez déclaré que do1() était virtuel. Mais pour l'instant, ça ne va pas compiler.

Vous aimeriez savoir pourquoi vous voulez faire cela, cependant.

+0

Mon erreur c'est virtuel. MS VC++ compile des classes avec des méthodes abstraites non implémentées et j'obtiens l'écoute au moment de l'exécution seulement quand la méthode abstraite est appelée. Je suppose que 0 est placé VTABLE pour de telles méthodes. – Max

4

Une méthode abstraite doit être implémentée pour que la classe soit instanciée. Il n'y a rien de tel que de vérifier si une méthode est implémentée, le compilateur va le faire pour vous. Dans ce cas, vous ne pouvez pas avoir un objet CBase car il a des méthodes abstraites.

1

Vous n'avez pas besoin de vérifier si la méthode est implémentée à l'exécution (vous ne pouvez pas dans ce cas de toute façon) car CBase doit implémenter do1() pour satisfaire l'héritage de ABase.

3

Le compilateur ne vous permettra pas de créer une instance d'un type qui ne définit pas toutes les méthodes abstraites. Dans votre exemple ci-dessus l'appel à nouveau CBase() va générer une erreur de compilation sur les lignes de "ne peut pas instancier le type abstrait".

+0

MS VC++ le compile. et je reçois une exception à l'exécution quand j'appelle une telle méthode. (J'ai fait une erreur dans le premier message, la méthode est virtuelle) – Max

1

Vous ne pouvez pas instancier le CBase car il est ... abstrait, c'est-à-dire qu'il n'implémente pas toutes les fonctions virtuelles pures de ses parents.

Le plus simple serait probablement de définir une implémentation de bout dans le ABase:

class ABase { 
public: 
void do1() { /* do nothing */ } 
}; 

class BBase: public ABase { 
public: 
void do1() { /* do something */ } 
}; 

class CBase: public ABase {}; 

ABase * base = rand() % 2 ? new BBase() : new CBase(); 
base->do1(); 
1

En supposant que vous vous souvenez de faire DO1(), vous pouvez vérifier virtuelle & :: ABASE DO1, & BBase :: DO1 et & CBase :: do1 à l'exécution. Je ne suis pas convaincu que comparer & ABase :: do1 et & CBase :: do1 retournera la même valeur juste parce que CBase n'a pas outrepassé la fonction, et si juste parce qu'il fait sur un système signifie qu'il le fera toujours. Bien que vous puissiez être en mesure de les tester lors de l'exécution, vous ne pourrez pas utiliser ces informations pour créer un objet de la classe CBase s'il n'est pas abstrait, car il ne pourra pas être compilé lorsqu'il le sera. Vous pouvez cependant le faire en "C": avoir une table de pointeurs de fonction qui peut être NULL, vérifier si l'un d'entre eux est NULL, et créer une structure d'une telle instance ou l'invoquer si elle n'est pas t.