我觉得之前已经问过这个问题,但我无法在SO上找到它,也无法在Google上找到任何有用的信息.也许"covariant"不是我正在寻找的词,但这个概念与函数的协变返回类型非常相似,所以我认为它可能是正确的.这是我想要做的,它给了我一个编译器错误:
class Base; class Derived : public Base; SmartPtrd = new Derived; SmartPtr b = d; // compiler error
假设这些课程充分充实......我想你明白了.它不能转换SmartPtr
成SmartPtr
某种不明原因.我记得在C++和许多其他语言中这是正常的,虽然目前我不记得为什么.
我的根本问题是:执行此赋值操作的最佳方法是什么?目前,我正在将指针拉出,将其SmartPtr
明确地向上转换为基类型,然后将其包装为新SmartPtr
的适当类型(请注意,这不会泄漏资源,因为我们的本地SmartPtr
类使用侵入式引用计数).那是漫长而凌乱的,尤其是当我需要将SmartPtr
另一个对象包裹起来时...任何快捷方式?
SmartPtr
并且SmartPtr
是SmartPtr
模板的两个不同的实例.这些新类不共享的继承问题Base
和Derived
做的.因此,你的问题.
执行此赋值操作的最佳方法是什么?
SmartPtrb = d;
不调用赋值运算符.这会调用copy-ctor(大多数情况下都会删除副本),就像你写的那样:
SmartPtrb(d);
提供需要SmartPtr
并实现它的复制者.赋值运算符也是如此.你必须写出copy-ctor和op =记住SmartPtr的语义.
复制构造函数和赋值运算符都应该能够采用不同类型的SmartPtr并尝试将指针从一个复制到另一个.如果类型不兼容,编译器会抱怨,如果它们兼容,你就解决了问题.像这样的东西:
templateclass SmartPtr { .... template SmartPtr(const SmartPtr &blah) // same logic as the SmartPtr copy constructor template SmartPtr &operator=(const SmartPtr &blah) // same logic as the SmartPtr assignment operator };
模板不是协变的,这很好; 想象在下列情况下会发生什么:
vectorva; va.push_back(new Apple); // Now, if templates were covariants, a vector could be // cast to a vector vector & vf = va; vf.push_back(new Orange); // Bam, we just added an Orange among the Apples!
要实现您要执行的操作,SmartPointer类必须具有模板化构造函数,该构造函数可以使用另一个SmartPointer或另一个类型的指针.你可以看一下boost :: shared_ptr,它就是这样做的.
templateclass SmartPointer { T * ptr; public: SmartPointer(T * p) : ptr(p) {} SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {} template SmartPointer(U * p) : ptr(p) {} template SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {} // Do the same for operator= (even though it's not used in your example) };