2010-02-03 5 views
2

J'ai rencontré un problème avec mes classes, en passant un objet const (structure polymorphe) à un constructeur explicite qui prend une référence const à la classe de base de cette structure polymorphe. Voici l'échantillon (ce n'est pas de mon code, il est pour l'explication ici)Passage explicite d'un objet const à un constructeur qui prend la référence const à une classe polymorphe

class Base 
{ 
... 
} 

class Derived:public Base 
{ 
... 
} 

class Problem 
{ 
    Problem(const Base&); 
... 
} 

void myFunction(const Problem& problem) 
{ 
    ... 
} 

int main() 
{ 
    //explicit constructor with non const object 
    Derived d; 
    Problem no1(d); //this is working fine 
    myFunction(no1); 

    //implicit constructor with const object 
    Problem no2=Derived(); //this is working fine, debugged and everything called fine 
    myFunction(no2); //is working fine 

    //explicit constructor with const object NOT WORKING 
    Problem no3(Derived()); //debugger jumps over this line (no compiler error here) 
    myFunction(no3); //this line is NOT COMPILING at all it says that: 
    //no matching function for call to myFunction(Problem (&)(Derived)) 
    //note: candidates are: void MyFunction(const Problem&) 
} 

Il semble que cela fonctionne très bien avec la deuxième version (explicite appel constructeur de problème) que si je rejetterai explicitement la objet dérivé de sa classe de base de base comme il:

Problem(*(Base*)&Derived); 

Je ne réalise pas la différence entre l'appel impicitly et explicitement le constructeur de la classe de problème. Merci!

+0

Vous avez activé "Base" et "Derived" dans votre déclaration de deuxième classe. Est-ce une faute de frappe? De plus, le commentaire "débogueur saute-t-il sur cette ligne" s'applique-t-il même lorsque vous compilez dans un profil 'Debug' sans optimisations? –

+0

Vous créez des objets de la classe de base et vous les transmettez - vous n'obtiendrez pas de comportement polymorphe. Vous avez besoin d'une référence ou d'un pointeur vers une classe de base pour obtenir le comportement souhaité. Casting n'est pas une solution. – dirkgently

+0

Le paramètre est la référence const, donc il y a la référence pour le comportement polymorphique. – user265149

Répondre

6

Le problème est que vous ne déclarant pas un objet, mais une fonction:

Problem no3(Derived()); 
// equivalent to: 
Problem no3(Derived); // with parameter name omitted 

Utilisation:

Problem no3((Derived())); 
// extra parens prevent function-declaration interpretation 
// which is otherwise required by the standard (so that the code isn't ambiguous) 

C'est une bizarrerie de la syntaxe de déclaration de C héritée par C++.

Autres exemples:

void f(int(a)); /* same as: */ void f(int a); 

void g() { 
    void function(int); // declare function 
    void function(int()); // we can declare it again 
    void function(int=42); // add default value 
    function();   // calls ::function(42) ('function' in the global scope) 
} 
// 'function' not available here (not declared) 

void function(int) {} // definition for declarations inside g above 
+0

Merde, vous avez raison. Merci beaucoup! Bien que je sois tombé sur le même problème il y a quelque temps, je n'y pensais tout simplement pas maintenant. – user265149

0

Pour référence ultérieure, ceci est une bizarrerie connue voir un autre StackOverflow thread comme l'analyse syntaxique le plus contrariant, à l'origine de ce surnom.

Questions connexes