我有问题。有两个类:
struct Base {
Base* retain() {
//retain here
return this;
}
};
struct Derived : Base {
};
Derived *d1 = new Derived();
Derived *d2 = d1->retain(); //error here: need to typecast to Derived*
Derived *d3 = (Derived*)d1->retain(); //OK
有没有办法以我不需要手动强制转换结果的方式重写retain()函数?换句话说:retain()应该返回派生类型的对象。
答案 0 :(得分:4)
template<typename T>
struct Base
{
T* retain()
{
return (T*)this;
}
};
struct Derived : Base<Derived>
{
};
Derived *d1 = new Derived();
Derived *d2 = d1->retain();
可替换地:
struct Base
{
template<typename T>
void retain(T** ptr)
{
*ptr = (T*)this;
}
};
struct Derived : Base
{
};
Derived *d1 = new Derived;
Derived *d2;
d1->retain(&d2);
答案 1 :(得分:0)
通常,当您执行您正在执行的操作时,Base类将具有虚拟析构函数。这允许运行时类型识别。
您可能还想写struct Derived : public Base
,包括关键字public
。
解释虚拟析构函数如下。
一个简单类的对象,缺少虚方法的类,只不过是内存中的数据集合。具有此类对象地址的代码无法通过查看对象来判断对象是基类还是派生类型。
但是,如果基类型至少有一个虚方法,则编译器会为该类型的每个对象添加一个隐藏指针。此指针指向一个表,该表除其他外,确切地标识对象的类型,从而使指针上的dynamic_cast<>()
和其他多态操作成为可能。
如果所有这些对您来说都是新手,那么我建议您尝试下一步:将一个空虚拟析构函数virtual ~Base() {}
添加到Base类,然后阅读dynamic_cast<>()
。接下来,您可能希望将基础retain()
设为虚拟,然后为Derived提供自己的,覆盖retain()
。
无论如何,除非你能得到更有针对性的建议,否则上述内容应该为你提供一些起点。祝你好运。