2017-07-29 3 views
2

Das ist eine seltsame Situation, in die ich geraten bin. Ich erwartete, für die Zeiger implizit upcast zu sein:Keine implizite Upcasting mit Funktionszeiger Argumente?

struct BaseClass 
{}; 

struct DerivedClass : BaseClass 
{}; 

void baseClassArgFunc(BaseClass* arg) {}   // Function taking BaseClass argument 
void derivedClassArgFunc(DerivedClass* arg) {}  // Function taking DerivedClass argument 

int main() 
{ 
    void (*pBaseFuncArg) (BaseClass*);  // Pointer to function taking BaseClass argument 
    void (*pDerivedFuncArg) (DerivedClass*); // Pointer to function taking DerivedClass argument 

    pBaseFuncArg = baseClassArgFunc;   // Assign pointer, works fine 
    pDerivedFuncArg = derivedClassArgFunc;  // Assign pointer, works fine 

    pBaseFuncArg = derivedClassArgFunc;   // A value of type void (*) (DerivedClass *arg) cannot be 
               // assigned to an entity of type void (*) (BaseClass *) 

    pDerivedFuncArg = baseClassArgFunc;   // A value of type void (*) (BaseClass *arg) cannot be 
               // assigned to an entity of type void (*) (DerivedClass *) 

    return 0; 
} 

Ich erwartete Leere Zuweisung (*) (DerivedClass *) baseClassArgFunc (Baseclass * arg) für nichtig zu erklären, sicher zu sein. Ich bin verwirrt. Ich denke, es gibt dann kein implizites Upcasting mit Funktionszeigerargumenten?

+0

** Ja **. Kein implizites Upcasting hier. – iBug

+0

Korrigieren. Nicht sicher, dass diese Frage wirklich eine Antwort jenseits von "Ja" bekommen kann. Suchst du mehr als das? – hvd

+0

@hvd: Etwas wie 'compatible_cast <>' für Funktionszeiger, Elementzeiger und Elementfunktionszeiger wäre nett ... – Deduplicator

Antwort

3

Ihre Klassen ändern, die Probleme zu entlarven:

struct BaseClass 
{ 
}; 

struct DerivedClass : BaseClass 
{ 
    int a; 
}; 

Dann

pBaseFuncArg = derivedClassArgFunc; 

unsicher ist:

void derivedClassArgFunc(DerivedClass* arg) { arg->a = 42; } 


int main() 
{ 
    void (*pBaseFuncArg) (BaseClass*) = derivedClassArgFunc; 
    BaseClass base; 

    //derivedClassArgFunc(&base); // Doesn't compile as expected 
    pBaseFuncArg(&base);   // Would be UB, base->i won't exist 
} 
+0

Ja, ich habe versucht, darüber nachzudenken, welcher Weg sicher oder unsicher wäre. Ich denke, der andere Weg ist sicher, aber es scheint, es gibt hier keine implizite Casting. – Zebrafish