【问题标题】:How does casting this pointer to an unrelated class work?将此指针转换为不相关的类如何工作?
【发布时间】:2021-10-01 04:39:54
【问题描述】:

这让我很困惑,因为如果“this”指向它自己的对象,那么如何转换它(没有继承)允许我访问其他类成员?考虑到它的地址没有改变,我认为我对编译器的确切转换“this”做了什么感到困惑。

template<class T>
class A 
{
public:
    void call_fn()
    {
        reinterpret_cast<T*>(this)->fn();
    }
};

class B
{
public:
    void fn()
    {
        std::cout << "B function called" << std::endl;
    }
};

int main()
{
    A<B> obj;
    obj.call_fn(); //prints out "B function called"
}

【问题讨论】:

  • 在这种情况下,演员表说“假设this 实际上是指向T 的指针”。编译器有义务为您服务。但假装并不能使它成为现实。无论发生什么,纯属意外。形式上,这个程序的行为是未定义的; C++ 标准并没有告诉你程序做了什么。如果B 更复杂,例如有fn 使用的数据成员,问题就会变得更清晰。

标签: c++ class casting reinterpret-cast


【解决方案1】:

非静态方法调用就像一个普通的函数调用,但有一个隐藏的this 参数指向对象。显示的代码大致等同于以下代码:

class A {};
class B {};

void B_fn(B* this);

void A_call_fn(A* this) {
    B_fn(reinterpret_cast<B*>(this));
}; 

void B_fn(B* this) {
    std::cout << "B function called" << std::endl;
}

int main() {
    A obj;
    A_call_fn(&obj);
}

A::call_fn() 将其A* this 参数类型转换为B*,然后调用B::fn() 并将该转换指针作为其B* this 参数值。 reinterpret_cast 实际上是一个蛮力强制转换,它真的竭尽全力尝试满足您的要求。因此,您是在告诉编译器您知道自己在做什么并接受它。确实如此。但是您正在调用未定义的行为,因为正如您所说,AB 是不相关的类型。

代码发生可以工作,但这只是因为B::fn()没有使用它的B* this参数,所以this是否实际上指向一个有效的@987654335并不重要@对象与否。代码最终与您这样做没有什么不同:

int main() {
    std::cout << "B function called" << std::endl;
} 

但是,如果您要更改 B 以保存 B::fn() 实际使用的非静态数据成员,那么代码将更加明显地失败。

【讨论】:

    猜你喜欢
    • 2019-10-07
    • 2021-09-20
    • 2013-11-23
    • 2014-07-04
    • 2016-05-10
    • 2015-03-15
    • 2013-08-17
    相关资源
    最近更新 更多