gpt4 book ai didi

c++ - 在 C++ 中转换函数指针的奇怪行为

转载 作者:IT老高 更新时间:2023-10-28 22:16:40 26 4
gpt4 key购买 nike

我最近在 C++ 中遇到了一个关于函数指针的行为,我无法完全理解。我向 Google 以及一些更有经验的同事寻求帮助,但他们也无能为力。

以下代码展示了这种神秘的行为:

class MyClass{
private:
int i;

public:
MyClass(): i(0) {}
MyClass(int i): i(i) {}

void PrintText() const { std::cout << "some text " << std::endl;}
};

typedef void (*MyFunction) (void*);

void func(MyClass& mc){
mc.PrintText();
}

int main(){
void* v_mc = new MyClass;
MyFunction f = (MyFunction) func; //It works!
f(v_mc); //It works correctly!!!

return 0;
}

所以,首先我定义了一个简单的类,以后会用到(特别是它的成员方法PrintText)。然后,我将名称对象 void (*) (void*) 定义为 MyFunction - 一个指向函数的指针,它有一个 void* 参数并且没有'不返回值。

之后,我定义函数 func() 接受对 MyClass 对象的引用并调用其方法 PrintText

最后,魔法发生在 main 函数中。我为新的 MyClass 对象动态分配内存,将返回的指针转换为 void*。然后,我将指向 func() 函数的指针转换为 MyFunction 指针 - 我根本没想到它会编译,但确实如此。

最后,我用 void* 参数 调用这个新对象,即使底层函数 (func()) 接受对 MyClass 对象。一切正常!

我尝试使用 Visual Studio 2010 (Windows) 和 XCode 5 (OSX) 编译此代码,它的工作方式相同 - 不会报告任何警告。我想这行得通的原因是 C++ 引用实际上是在幕后作为指针实现的,但这不是解释。

我希望有人能解释这种行为。

最佳答案

正式的解释很简单:未定义的行为是未定义的。当您通过指向不同函数类型的指针调用函数时,它是未定义的行为,程序可以合法地做任何事情(崩溃,似乎工作,在线订购披萨......任何事情都可以)。

您可以尝试推理您遇到的行为发生的原因。这可能是以下一种或多种因素的组合:

  • 您的编译器在内部将引用实现为指针。
  • 在您的平台上,所有指针都具有相同的大小和二进制表示。
  • 由于 PrintText() 根本不访问 *this,编译器可以有效地完全忽略 mc 的值而只是调用func 中的 PrintText() 函数。

但是,您必须记住,虽然您目前在当前平台、编译器版本和当前月相下遇到了您所描述的行为,但这种情况可能会随时发生变化,而没有任何明显的原因(例如周围代码的变化会触发不同的优化)。请记住,未定义的行为只是未定义的。


至于为什么你可以将 &func 转换为 MyFunction - 标准明确允许这样做(使用 reinterpret_cast,C 风格的cast 在这种情况下翻译)。您可以合法地将指向函数的指针转换为指向函数类型的任何其他指针。但是,几乎唯一可以合法使用它的方法就是移动它或将其转换回原始类型。正如我上面所说的,如果你通过错误类型的函数指针调用,这是未定义的行为。

关于c++ - 在 C++ 中转换函数指针的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26506217/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com