Cast function pointers that differs by argument type

一曲冷凌霜 提交于 2019-12-11 20:18:30

问题


Why this is not legal:

class Base
{
public:
    Base(){};
    virtual ~Base(){};
};

class Derived : public Base{};

void takeDerived(Derived * c){};

// main
void(*ptr)(Base*) = static_cast<void(*)(Base*)>(&takeDerived); // doesn't work

// but this work ok, as well as reinterpret_cast
// void(*ptr)(Base*) = (void(*)(Base*))(&takeDerived);

Derived is a Base. Why can't it be casted in function parameter? For example, I can do this easily even without casting:

void takeBase(Base* c){};
takeBase(new Derived{});

回答1:


It's just designed to be that way. A Base isn't a Derived. The is-a relationship for class derivation can't be reversed.

The type of a function parameter means "accept", while the type of an object means "fit". Casting the type of a function changes what it accepts. It's dangerous to allow a function to accept whatever isn't what it originally accepts.

Consider this code:

class Base {};
class Derived : public Base {
    public:
    int t;
    void useDerived() {}
};

void useDerived(Derived *d){
    d->useDerived();
}

What should happen if a Base object is passed?

Base b;
((void(*)(Base*))useDerived) (&b);

Even worse, what if another derivation of Base is passed?

class AnotherDerived : public Base {
    public:
    double t;
    void useDerived() {}
};
AnotherDerived ad;
((void(*)(Base*))useDerived) (&ad);



回答2:


Yes, but you're trying to do it the other way around. You cannot do

void takeDerived(Derived *c) { }

...

Base b;
takeDerived(&b);

The function pointer cast you're trying to do would enable these shenanigans; you could do

void (*ptr)(Base*) = takeDerived;
Base b;
ptr(&b); // Oops.

Then things would explode, and that would be bad.



来源:https://stackoverflow.com/questions/27132333/cast-function-pointers-that-differs-by-argument-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!