我无意间调用了没有自己的类对象的成员函数。但这如何工作?

问题描述 投票:2回答:4

这是我的代码。

class IService {
};

class X_Service {
public:
    void service1() {
        std::cout<< "Service1 Running..."<<std::endl;
    }
};


int main() {
    IService service;
    auto func = reinterpret_cast<void (IService::*)()>(&X_Service::service1);
    (service.*(func))();
    return 0;
}

我不知道这是如何工作的。我没有继承IService,也没有创建X_Service对象,但是它可以工作。有人可以解释吗?

c++ reinterpret-cast
4个回答
7
投票
您的困惑可能是由于误解,因为某些东西可以编译并运行而不会崩溃,所以它“起作用”。这不是真的。

您可以通过多种方式打破语言规则,仍然编写可编译和运行的代码。通过在此处使用reinterpret_cast并进行无效的转换,您已经破坏了语言规则,并且您的程序具有未定义的行为。

这意味着它似乎可以工作,可能崩溃或只能做与您想要的完全不同的事情。

在您的情况下,它似乎可以正常工作,但是它仍然是UB,并且代码无效。


2
投票
在底层,编译器会将所有这些功能转换为机器代码,基本上只是跳转到内存中的某些地址,然后执行存储在其中的命令。

成员函数只是一个函数,除了局部变量和参数外,还具有一块存储类对象地址的内存。该内存保留使用this关键字时要访问的地址。

如果您在错误的对象或nullptr上调用成员函数,则基本上只是使this指针指向无效的对象。

您的功能无法访问this,这就是您的程序不会崩溃的原因。

也就是说,这仍然是未定义的行为,任何事情都可能发生。


0
投票
当您reinterpret_cast指向不同类型的函数或成员函数指针时,除非您首先将其转换回其原始类型并对其进行调用,否则永远不允许调用结果指针。

违反此规则将导致undefined behavior。这意味着您失去了任何语言保证,即程序将以任何特定方式运行,而没有来自特定编译器的其他保证。

reinterpret_cast通常很危险,因为它完全绕过了类型系统。如果使用它,则需要始终通过查看语言规则来验证自己,是否明确定义了强制类型转换和使用结果的方式。 reinterpret_cast告诉编译器您知道自己在做什么,并且即使结果是无意义的,也不希望出现任何警告或错误。


0
投票
所以,我玩得很开心,并稍微操纵了代码。这也是一个经验答案。这种作法有很多陷阱可能会导致堆栈损坏,因此,我对代码进行了一些更改,以使其不出现堆栈损坏,而只是显示发生了什么。

#include <iostream> class IService { public: int x; }; class X_Service { public: int x; void service1() { this->x = 65; std::cout << this->x << std::endl; } }; int main() { IService service; auto func = reinterpret_cast<void (IService::*)()>(&X_Service::service1); (service.*(func))(); std::cout << service.x << std::endl; std::cin.get(); X_Service derp; (derp.service1)(); std::cout << derp.x << std::endl; return 0; }

因此,从一开始,auto赋予了创建无类型安全指针void (IService::*)()的权力,而对象本身的实例为this->,无论您从其隐身继承的任何类的成员函数是什么。唯一的问题是,变量是根据您隐身继承的类来解释的,如果类型不同,则可能导致堆栈损坏。

方式很酷,但不可避免地会导致堆栈损坏,您可以做以下有趣的事情。

class IService { public: char x; };

您的IDE将检测到您的IService对象的堆栈损坏,但得到的输出是

65 A

是值得的,但是您会发现在进行这种隐式继承时会出现问题。

我也在使用86x编译器。因此,基本上我的变量都已对齐。假设例如,如果我在Iservice的int x上方添加int y,则此程序将输出废话。基本上它仅能工作,因为我的类是二进制兼容的。

© www.soinside.com 2019 - 2024. All rights reserved.