2010-07-27 8 views
3

Pourquoi une erreur de compilation se produit-elle lorsque j'appelle une fonction de classe de base avec un pointeur sur un pointeur vers une classe héritée?Héritage et pointeurs vers des pointeurs: pourquoi cela ne fonctionne-t-il pas et comment le contourner?

Exemple:

class cFoo {}; 
class cBar : public cFoo {}; 
void func1(cFoo *) {} // base class 
void func2(cFoo **) {} // base class 

void main(void) 
{ cBar bar, *pbar; // inherited class 

    func1(&bar); // compiles OK 
    func2(&pbar); // fail 
    func2(dynamic_cast<cFoo**>(&pbar)); // 'class cFoo ** ' : invalid target type for dynamic_cast 
} 

Comment puis-je contourner cela?

Répondre

2

Cela ne fonctionne pas car dynamic_cast fonctionne sur les pointeurs ou les références aux classes. Et vous essayez de l'utiliser sur des pointeurs vers des pointeurs.

La solution simple serait quelque chose comme ceci:

func2(&dynamic_cast<cFoo*>(pbar)); 
+2

N'est-ce pas prendre l'adresse d'un temporaire? Est-ce vraiment autorisé? –

+1

@Ands qu'en est-il de 'dynamic_cast ' alors? –

6

Considérez ce qui suit:

class cFoo {}; 
class cBar : public cFoo {}; 
void func1(cFoo *) {} 
void func2(cFoo **p) { *p = new cFoo; } // modify pointee 

void main(void) 
{ cBar bar, *pbar; // inherited class 

    func1(&bar); // compiles OK 

    func2(&pbar); 
} 

Si cela a fonctionné, vous auriez réussi à mettre un objet OOFC dans un pointeur CBAR sans erreur de compilation, et le système de type serait subverti. Une distribution dynamique n'aiderait pas, car il n'y a aucun moyen que la distribution puisse empêcher les dommages.

0

Ce que vous essayez de faire est défectueux.

Le cas typique d'utilisation d'un pointeur (non const) en tant qu'argument de fonction est que la fonction modifie l'argument pour qu'il pointe vers un pointeur de certaines instances.

C'est la fonction qui choisit l'instance. Exemple d'une méthode d'usine.

Le type d'argument décrit le type que la fonction garantit être valide.

Si votre fonction garantissait que l'instance était un cBar, elle devrait prendre un argument cBar **.

Comme il prend un cFoo **, il garantit seulement que l'objet est un cFoo valide.

Dans la forme actuelle, si vous forcez une distribution, tout type de cFoo sera exposé en tant que cBar - même si ce n'est pas le cas.

+0

Oui, je soupçonnais que c'était le problème. Je ne peux pas m'attendre à ce que func2() sache qu'il est passé un cBar **. Dans la vraie vie, je fais exactement ce que TomW montre ci-dessus (allocation de mémoire). Soupir ... Je peux contourner cela, mais ce ne sera pas aussi élégant. Merci à tous pour votre aide rapide et experte. – Pierre