我正在使用的代码有自己的智能指针实现,它执行简单的引用计数。是的,我们不应该有自己的实现。是的,我们应该使用 boost 中的一个或类似的。忍受我。
我发现我想写这样的代码:
...
CountedPointer<Base> base;
...
CountedPointer<Derived> derived;
...
base = derived;
但是,CountedPointer 的复制构造函数有一个这样的原型:
CountedPointer(const CountedPointer<T> &other);
所以上面的代码无法编译,因为它找不到合适的构造函数(或赋值运算符 - 那里是同样的故事)。我尝试用这样的原型重写复制构造函数:
template<U>
CountedPointer(const CountedPointer<U> &other);
但是,我遇到了一个问题,即复制构造函数必须访问它正在复制的对象的私有成员(即原始指针),如果它位于不同的 CountedPointer 特化中,它们是不可见的。
Alexandrescu 在他的Loki库中通过封装指针的访问器函数避免了这个问题,但如果可能的话,我不希望直接访问原始指针。
有什么办法可以写这个来允许派生到基本副本,但不允许一般访问原始指针?
更新: 我已经实现了下面接受的答案,并且效果很好。当我只提供复制构造函数的模板版本,替换原始的未模板版本时,我花了一段时间弄清楚为什么我的程序会出现可怕的段错误。最终,我意识到编译器并不将模板版本视为复制构造函数,而是提供了一个默认版本。默认的只是愚蠢地复制内容而不更新计数器,所以我最终得到了悬空指针和双重释放。同样的事情也适用于赋值运算符。