2017-07-29 6 views
2

これは私が遭遇した奇妙な状況のようなものです。ポインタは、暗黙的にアップキャストするために私が期待される:関数ポインタ引数を使用した暗黙のアップキャストはありませんか?

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; 
} 

私は安全であるとbaseClassArgFunc(BaseClassの*引数)をvoidに無効(*)(DerivedClass *)を割り当てると予想しました。よくわかりません。関数ポインタの引数を暗黙的にアップキャストする必要はないと思いますか?

+0

**はい**。ここでは暗黙的なアップキャストはありません。 – iBug

+0

修正。この質問が本当に「はい」以外の答えを得ることができるかどうかはわかりません。あなたはそれ以上のものを探していますか? – hvd

+0

@hvd:function-pointer、member-pointer、member-function-pointerのための 'compatible_cast <>'のようなものはいいでしょう... – Deduplicator

答えて

3

の問題を公開するために、あなたのクラスを変更する:

struct BaseClass 
{ 
}; 

struct DerivedClass : BaseClass 
{ 
    int a; 
}; 

が続い

pBaseFuncArg = derivedClassArgFunc; 

が安全であるために:

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

ええ、私はどちらの方法が安全か危険なのか考えようとしていました。私は他の方法は安全だと思いますが、暗黙的なキャスティングはここにないようです。 – Zebrafish

関連する問題