我喜欢在临时基础上应用外墙,而不是将它们烘焙到课堂本身。但我需要对数据进行操作,因此我需要从外观访问this
。这是一个小例子:
#include <array>
#include <iostream>
template <typename T>
struct x_getter
{
friend T;
double x() const
{
return (*real_self)[0];
}
void x(double new_x)
{
(*real_self)[0] = new_x;
}
private:
T* real_self = reinterpret_cast<T*>(this);
x_getter() = default; //prevents accidental creation
};
struct coordinates : std::array<double, 3>, x_getter<coordinates>
{
using std::array<double, 3>::array;
};
int main()
{
coordinates origin{};
std::cout << origin.x();
origin.x(12.7);
std::cout << ' ' << origin.x() << '\n';
}
It segfaults。一段时间使用类似的东西,我不幸的是能够逃脱它。
如何在Facade类中使用具有目标类类型的this
?
在对象内部的某个地方,以无序的方式,有数组和x_getter
。通过reinterpret_cast
,我试图欺骗它认为this
是coordinates
,但当它执行operator[]
时,使用的偏移是咬掉,离开物体,因此分裂。
答案 0 :(得分:3)
这里的问题是reinterpret_cast
不起作用,因为this
指针没有指向coordinates
类的开头,因为它在继承自{array
之前继承自x_getter
1}}。此类的内存布局如下所示:
coordinates
|- std::array<double, 3>
|- x_getter
当您使用reinterpret_cast<T*>(this)
时,this
指针中存储的地址是x_getter
对象的地址,但您强制编译器假定它实际上是coordinates
的地址宾语。因此,取消引用这样的指向派生类的指针会导致各种未定义的行为。
通常,CRTP应在方法内使用static_cast
:
double x() const
{
return (*static_cast<TDerived const *>(this))[0];
}
与reinterpret_cast
不同,static_cast
会正确调整this
指针以正确指向派生对象。