c++ - 取消引用向上转换的成员函数指针

标签 c++

假设我有 2 个类 InstrumentBrass,其中 Brass 派生自 Instrument:

class Instrument
{
protected:
 std::string _sound;
public:
 Instrument(std::string sound) : _sound(sound) {}
 virtual void play() { std::cout << _sound << std::endl; }
};

class Brass : public Instrument
{
private:
 std::string _pitchShifter;
public:
 Brass(std::string pitchShifter) : Instrument("braaaaaa"), _pitchShifter(pitchShifter)
 {}

 void printPitchShifter() { std::cout << _pitchShifter << std::endl; }
}

出于某种疯狂的原因,我有一个指向 Instrument 成员函数的指针:

typedef void(Instrument::*instrumentVoidFunc)() //declaring member function pointers is too damn confusing
instrumentVoidFunc instrumentAction;

现在显然,这将有效,具有明确定义的行为:

Instrument soundMaker("bang!");
instrumentAction = &Instrument::play;
(soundMaker.*instrumentAction)();

输出应该是bang!

但我也可以通过向上转换来使 instrumentAction 指向 Instrument存在的 Brass 成员函数,如下所示:

instrumentAction = static_cast<instrumentVoidFunc>(&Brass::printPitchShifter);

我的理解是(或者无论如何),向上转换成员函数指针应该会破坏它引用基类中尚未存在的派生类函数的任何能力。但是:

Brass trumpet("valves");
(trumpet.*instrumentAction)();

...打印出 valve 就像我正常调用派生类上的函数一样。因此,显然向上转换派生类函数指针不会影响在派生类上取消引用它时发生的情况(尽管在基类上取消引用它会产生未定义的行为)。

编译器到底是如何实现这一点的?

最佳答案

虽然函数指针强制转换是可能的,但通过与原始类型不匹配的函数类型调用函数是未定义的行为。允许函数指针强制转换的原因是支持强制转换并存储公共(public)类型,但通过在调用函数指针之前将函数指针强制转换回来来恢复正确的类型。此限制的基本背景是,即使是兼容的指针也可能需要在使用时进行调整。隐藏正确的签名意味着存在合适的蹦床(即函数指针需要具有附加状态)。

关于c++ - 取消引用向上转换的成员函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27557056/

相关文章:

c++ - 派生类与基类的 std::shared_ptr 的使用

c++ - 从 Assimp 加载 Collada (dae) 模型显示法线不正确

c++ - map [] 运算符段错误

c++ - 如何使 udev deamon "think"我们添加了一条新规则?

c++ - 处理闪现窗口事件

c++ - const char* 连接

c++ - 在 Linux 上增加文件需要任何费用吗?

c++ - 模板特化问题

c++ - 寻找插入 vector 的最佳位置

C++ 我在设置我创建的类的优先级队列时遇到问题