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

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

这是我的代码。

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
3个回答
3
投票
您的困惑可能是由于误解,因为某些东西可以编译并运行而不会崩溃,所以它“起作用”。这不是真的。

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

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

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


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

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

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

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

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


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

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

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

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