c++ - 转换因参数类型而异的函数指针

标签 c++ casting function-pointers

为什么这是不合法的:

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 是一个Base。为什么不能在函数参数中进行转换?例如,即使没有转换,我也可以轻松地做到这一点:

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

最佳答案

它就是这样设计的。 Base 不是 Derived。类派生的 is-a 关系无法逆转。

函数参数的类型意味着“接受”,而对象的类型意味着“适合”。转换函数的类型会改变它接受的内容。允许一个函数接受任何不是它最初接受的东西是危险的。

考虑这段代码:

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

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

如果传递了一个 Base 对象会发生什么?

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

更糟糕的是,如果传递了 Base 的另一个推导怎么办?

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

关于c++ - 转换因参数类型而异的函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27132333/

相关文章:

c++ - 不同行为 : Calling Function Directly vs. 通过非静态成员指针

C++ 类成员函数到 C 结构函数指针

c - 如果我转换一个函数指针,改变参数的数量会发生什么

c++ - 如果我们有 (N)RVO,何时实际调用 move 构造函数?

C# 将 List<ObjBase> 转换为 List<Obj>

postgresql - SQL 错误 [22P02] 无法识别 where 子句中的 varchar 转换为整数

c# - 为什么 <enum> 的集合无法转换为 <int?>?

c++ - 在单元安全代码中处理文字零

c++ - 如何确保虚基类的赋值运算符只被调用一次?

c++ - VS 2013 - IntelliSense 报告误报?