将基类模板的“this”类型转换为其派生类
Typecasting `this` of a base class template to its derived class
我的代码的简化版本如下:
template <class T>
struct Base
{
void SayHello( T* aDerived )
{
}
void SaySomething()
{
SayHello( this ); // This is where the error happens
}
};
struct Derived : public Base< Derived >
{
};
int main(int argc, const char * argv[])
{
Derived iDerived;
iDerived.SaySomething();
}
它不会在SayHello( this )
行上编译,并显示以下错误信息:
Cannot initialize a parameter of type 'Derived *'
with an rvalue of type 'Base<Derived> *'
现在编译器抱怨这个是有意义的,尽管在我看来有点愚蠢,如果我删除这一行,它不会抱怨:
iDerived.SaySomething();
无论如何,这个问题可以通过显式类型转换来解决,如下所示:
SayHello( (T*)this );
问题是我的实际代码最终会有许多这样的类型转换,在我看来,在Base
中包含一些允许它自动类型转换到它的模板类(T
)的东西是合理的。
我要的是operator=
吗?有人可以提供一个代码样本,这是如何做到的?这个问题建议我可以这样做:
强制转换总是在this
和T*
之间。
operator T*()
{
return (T*)this;
}
您可以添加一个辅助函数,将this
向下转换为派生类型
template <class T>
struct Base
{
void SayHello( T* aDerived )
{
}
void SaySomething()
{
SayHello( derived_this() );
}
private:
T* derived_this()
{
return static_cast<T*>(this);
}
您可能还需要const
重载:
const T* derived_this() const
{
return static_cast<const T*>(this);
}
您可以添加隐式转换操作符,但我不建议这样做:
operator T*() { return static_cast<T*>(this); }
隐式转换削弱了类型系统,并可能成为bug的来源,我认为像derived_this()
这样的显式函数更清晰、更安全。
虽然在我看来有些愚蠢,但它不会抱怨如果我删除这一行[…]
不,这并不愚蠢,这就是模板的工作原理。如果不调用类模板的成员函数,它将永远不会被实例化。因此,在实例化它们时产生的编译错误将不会显示。
这个问题可以通过显式的类型转换来解决,像这样[…]
我更喜欢static_cast<>
:
SayHello( static_cast<T*>(this) );
SaySomething()
函数接收到的this
指针是Base<Derived>
类型的,但是你知道(通过设计)指向的对象实际上是Derived
类型的。因此,执行静态强制转换是安全的。
在这种情况下,多次强制转换指针没有问题。这就是CRTP(您正在使用的设计模式)强迫您做的事情。如果您对此感到困扰,只需定义一个在我看来,在Base中包含一些允许它自动被类型转换到它的模板类(T)的东西是合理的。
get_this()
函数来为您执行强制转换:
template <class T>
struct Base
{
void SayHello( T* aDerived )
{
}
void SaySomething()
{
SayHello( get_this() );
}
private:
// Version returning a non-const pointer
T* get_this() { return static_cast<T*>(this); }
// Version returning a const pointer
T const* get_this() const { return static_cast<T const*>(this); }
};
相关文章:
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- C++ 类型转换基础 PTR 到派生 PTR 保存在引用类中
- 派生到基本隐式指针类型转换
- decltype 所需的不完整类型的派生到基数转换
- 如何避免使用模板类型的派生类进行多态性动态强制转换
- 使用派生模板化类的正确类型转换访问基类中的数据
- 将派生类型转换为基本类型
- 如何使用基类指针调用派生类非虚拟成员函数,而无需类型转换和使用多态性
- 为什么我们需要从基类型转换为派生类型并返回
- C++ 多态性和派生类类型 - "ugly programming"指针类型转换
- 将派生类的ptr类型转换为ptr类型
- 将基类模板的“this”类型转换为其派生类
- 对不同派生类的增强反序列化进行正确的类型转换
- vector迭代的派生和基之间的类型转换:C2664错误