2015-07-14 4 views
2

Dans le code suivant, je peux affecter le retour du D::clone() à un pointeur sur B, mais pas un pointeur sur D. Est-il possible de renvoyer le type polymorphe réel à partir d'un appel du pointeur de base?Erreur de conversion non valide C++ utilisant des types de retour covariant avec des fonctions virtuelles

struct B 
{ 
    virtual B * clone() { return this; } 
}; 

struct D : B 
{ 
    D * clone() 
    { 
     std::cout << std::is_same<decltype(this), D *>::value << std::endl; 
     return this; 
    } 
}; 

int main() 
{ 
    B * b = new D(); 
    B * bb = b->clone(); // prints "1" 
    std::cout << std::is_same<decltype(b->clone()), D *>::value << std::endl; // prints "0" 
    D * d = b->clone(); // error: invalid conversion from B * to D * (GCC 5.1) 
} 
+1

compilateur est bon -.. Par' b-> clone() 'vous appelez cette fonction' B * B :: clone() 'mais de façon polymorphe, le compilateur verrait le type covariant si' b'était de type D * '- pas de type B *' ... – PiotrNycz

Répondre

4

Non Un appel de clone() sur la base d'une classe BD retournera la distribution D* à un B*.

Vous pouvez inverser cela en faisant un static_cast<D*> si vous êtes absolument certain, ou un dynamic_cast<D*> si vous n'êtes pas certain. Si vous êtes certain, que vous devriez vraiment faire la variable b être un D*.

En C++, vous devez encoder ce que vous savez de l'état du programme au moment de la compilation, quelle que soit la situation d'exécution en tant que types. En stockant le D* dans B* b, vous dites au compilateur pas de «savoir» que les données pointant vers «est un D». Au lieu de cela, vous dites « le code à l'aide B*b doit être valable pour tout pointeur-to-B Il est clair que D* d = b->clone(); n'est pas garanti d'être valide pour chaque pointeur-to-B

+0

Ce que j'essaie réellement de faire, c'est de déterminer le type dynamique d'un objet d'un pointeur à la base, et je ne peux pas utiliser le type de changement dynamic_cast parce que les objets dérivés sont des classes de template avec des arguments de type inconnus. le modèle de visiteur, mais il semble qu'il n'y a pas moyen de contourner le problème – ThomasMcLeod

+0

@ThomasMcLeod est-il une opération fixe que vous voulez faire sur les objets dérivés? arguments avez-vous besoin de savoir? Essayez-vous de déclencher une double répartition, où les détails de l'opération dépendent de deux bases de code distinctes? Essayez de poser des questions sur votre problème particulier, avec une solution essayée, et pourquoi vous ne l'aimez pas. Demander simplement comment résoudre un sous-problème (sans le contexte plus large) peut souvent restreindre la capacité des gens à trouver des solutions. – Yakk

+0

Non, il n'y a pas d'opération fixe, mais l'opération dépend du type dynamique, c'est donc le problème. J'ai en fait une solution complète en utilisant le modèle de visiteur, mais je voulais connaître la réponse à ce sous-problème indépendamment. – ThomasMcLeod