如果我已经回答了这个问题,但我找不到答案,我提前道歉。
注意:这是家庭作业,所以如果您觉得回答起来不自在,我完全理解。
我有以下内容:
ptr.h:
template<typename T>
class Ptr {
T* address;
size_t* counter;
Ptr(T* address) : address(address), counter(new size_t(1)) { }
Ptr(const Ptr& other) : address(other.address), counter(other.counter)
{
++(*counter);
}
virtual ~Ptr() {
if (0 == --(*counter)) { delete address; delete counter; }
}
Ptr& operator=(const Ptr& right) {
if (address != right.address) {
if (0 == --(*counter)) { delete address; delete counter; }
address = right.address;
counter = right.counter;
++(*counter);
}
return *this;
}
T& operator*() const { TRACE(address); return *address; }
T* operator->() const { TRACE(address); return address; }
T* raw() const { TRACE(addr); return addr; }
};
主.cc:
#include <iostream>
#include "ptr.h"
using std::cout;
using std::endl;
class Base {
public:
Base() { std::cout << "Base()" << std::endl; }
virtual ~Base() { std::cout << "~Base()" << std::endl; }
virtual std::string str() { return "In Base::str()"; }
};
class Derived: public Base {
public:
Derived() { std::cout << "Derived()" << std::endl; }
~Derived() { std::cout << "~Derived()" << std::endl; }
std::string str() { return "In Derived::str()"; }
};
int main() {
Ptr<Base> base(new Base());
Ptr<Derived> derived(new Derived());
Ptr<Base> pbase(0);
Ptr<Derived> pderived(0);
// upcasting can be done like this, but is it the best way?
pbase = *((Ptr<Base>*)(&derived));
cout << pbase->str() << endl; // outputs: "In Derived::str()"
/*
* downcasting should be done using dynamic_casts
* but how can I downcast here?
* what do I know so far:
* 1. just because Derived is a subclass of Base does not mean Ptr<Derived> is a
* subclass of Ptr<Base> so there is no hierarchy between the two so I cannot
* really use dynamic_casts here
* 2. The dynamic_cast I do use is sort of useless no? since pbase is a Ptr<Base>
*/
pderived = *((Ptr<Derived>*)(dynamic_cast<Ptr<Base>*>(&pbase)));
cout << pderived->str() << endl;
return 0;
}
现在,目标是使用 dynamic_cast 来回移动,虽然我发现了很多关于智能指针的有趣花絮,但没有真正解释如何这是如何实现的。
我尝试只获取 pbase 的地址字段,然后使用该地址将 pderived 初始化为一个新的 Ptr,但当然我的引用计数都搞砸了。
我尝试创建一个新的 Ptr,其中包含对 pderived 计数器的引用,但后来我无法设置 pderived 的地址字段,所以我也被困在那里。
我告诉你们这些信息是因为: 1. 我想说明一点,在在线寻求帮助之前,我已经为此工作了很长时间,并且 2. 我想让你知道我已经尝试过什么。
我真的可以在这里使用一些建议。获取方式:
pderived = <SOMETHINGSOMETHING>pbase<SOMETHINGSOMETHING>
谢谢!
最佳答案
通常,智能指针类将公开一个动态转换包装器,以正确处理底层智能指针对象。例如,C++0x 有 dynamic_pointer_cast功能。请注意,您的 *((Ptr<Derived>*)(dynamic_cast<Ptr<Base>*>(&pbase)));
可以而且将会中断,特别是如果你有多重继承,因为它不会调整 address
处的内部指针。到子类中的正确偏移量以获得所需的任何父类(super class)。
在实现层面,一个引用计数智能指针类通常会在每个智能指针中携带两个指针;一个直接指向对象(正确地转换为指针的任何类型),一个指向一个包含引用计数的结构,一个指向原始对象的指针,和一个指向删除例程的指针 .这允许指针的任何转换变体正确取回原始对象并调用其析构函数。目前你正指向一个size_t
,它不会为您提供此信息。
无论如何,一旦你有了析构函数的间接寻址,当需要转换这些智能指针时,你就可以只转换外部指针;当销毁时间到来时,单独留下这个内部引用计数结构。
当然,实际上把这一切都变成代码,留给读者作为练习:)
关于c++ - 智能指针和 dynamic_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10263902/