[英]Dereferencing upcasted member function pointers
假设我有2个类Instrument
和Brass
,其中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)();
...打印出valves
就像我在派生类上正常调用该函数一样。 因此,显然,向上转换派生类函数指针不会影响在派生类上对其进行取消引用时发生的事情(尽管在基类上对其进行取消引用会导致未定义的行为)。
编译器究竟如何做到这一点?
尽管可以进行函数指针强制转换,但通过与原始类型不匹配的函数类型调用函数是未定义的行为。 允许使用函数指针强制转换的原因是为了支持强制转换并存储通用类型,但在调用函数指针之前将其返回强制恢复正确的类型。 此限制的基本背景是,即使兼容的指针也可能需要在使用时进行调整。 隐藏正确的签名将意味着存在一个合适的蹦床(即,函数指针将需要具有其他状态)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.