2009-09-04 4 views
1

Quelqu'un peut-il expliquer pourquoi le code suivant n'est pas valide? Est-ce parce que le décalage de la variable d est différent de la variable b?Erreur d'appel de la fonction et passage d'une référence à un pointeur avec un type dérivé

class Base { public: int foo; }; 

class Derived : public Base { public: int bar; }; 

int DoSomething(Base*& b) { return b->foo; } 

Base* b = new Derived; 
Derived* d = new Derived; 

int main() 
{ 
    DoSomething(d); 
} 

C'est l'erreur qui the online Comeau C++ compiler donne:

"ComeauTest.c", line 12: error: a reference of type "Base *&" (not const-qualified) 
      cannot be initialized with a value of type "Derived *" 
    DoSomething(d); 
       ^

C'est une question similaire, mais est différent parce que, dans mon exemple, je déclare d comme un type de pointeur: Passing references to pointers in C++

Remarque que cela compile quand je passe b à DoSomething.

Répondre

10

Imaginez que vous pourriez faire cela. La référence n'est pas const, il est donc possible que DoSomething soit assigné au pointeur et qu'il soit visible dans l'appelant. En particulier, dans DoSomething, il est possible de changer le pointeur pour pointer vers quelque chose qui n'est pas une instance de Derived. Si l'appelant tente alors de faire des choses spécifiques au pointeur après le retour, il explose.

3

Cela n'a rien à voir avec les décalages. Notez que Derived dans votre exemple a à la fois foo et bar comme champs (et oui, ils auront des décalages différents, mais ceci n'est pas pertinent ici).

Si cela était autorisé, il ne serait pas de type sécurisé. Considérez ce code:

class Base { public: int foo; }; 

class Derived1 : public Base { public: int bar; }; 

class Derived2 : public Base { public: float baz; }; 

void DoSomething(Base*& b) { b = new Derived2; } 

Derived1* d = new Derived1; 
DoSomething(d); // d is of type Derived1*, but now points to object 
       // of incompatible type Derived2 
3

DoSomething Suppose ont été définis comme ceci:

int DoSomething(Base*& b) { b = new Base; } 

Oops, maintenant, quand principale appelle DoSomething, d finit par pointer à une base et non un Derived du tout.