将此指针投射到不相关的 class 是如何工作的?
How does casting this pointer to an unrelated class work?
这让我感到困惑,因为如果“this”指向它自己的对象,如何转换它(没有继承)允许我访问其他 class 成员?考虑到它的地址没有改变,我想我只是对转换“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
参数指向对象。显示的代码 大致 等同于以下内容:
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
实际上是一种蛮力转换,它确实竭尽全力满足您的要求。因此,您是在告诉编译器您知道自己在做什么并接受它。确实如此。但是您正在调用 未定义的行为,因为正如您所说,A
和 B
是不相关的类型。
代码 碰巧 可以工作,但这只是因为 B::fn()
没有使用它的 B* this
参数,所以 this
实际上是否指向一个有效的 B
对象。该代码最终与您执行此操作没有什么不同:
int main() {
std::cout << "B function called" << std::endl;
}
但是,如果您要更改 B
以保存 B::fn()
实际使用的非静态数据成员,那么代码将失败得更明显。
这让我感到困惑,因为如果“this”指向它自己的对象,如何转换它(没有继承)允许我访问其他 class 成员?考虑到它的地址没有改变,我想我只是对转换“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
参数指向对象。显示的代码 大致 等同于以下内容:
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
实际上是一种蛮力转换,它确实竭尽全力满足您的要求。因此,您是在告诉编译器您知道自己在做什么并接受它。确实如此。但是您正在调用 未定义的行为,因为正如您所说,A
和 B
是不相关的类型。
代码 碰巧 可以工作,但这只是因为 B::fn()
没有使用它的 B* this
参数,所以 this
实际上是否指向一个有效的 B
对象。该代码最终与您执行此操作没有什么不同:
int main() {
std::cout << "B function called" << std::endl;
}
但是,如果您要更改 B
以保存 B::fn()
实际使用的非静态数据成员,那么代码将失败得更明显。