转换多态智能指针对象

时间:2015-05-29 19:05:35

标签: c++ casting polymorphism smart-pointers dynamic-cast

我实现了以下智能指针模板类:

#ifndef __ProjectManager__mSharedPtr__
#define __ProjectManager__mSharedPtr__

#include <stdio.h>
#include "RefCount.h"

template <class T>
class mSmartPtr {

    T *data;
    RefCount *rc;

public:

    mSmartPtr(T* srcPtr);
    mSmartPtr(const mSmartPtr&);
    ~mSmartPtr();
    T* operator->() const;
    T& operator*() const;
    mSmartPtr<T>& operator=( mSmartPtr&);
    mSmartPtr<T> operator()(mSmartPtr&);
};

template<class T>
mSmartPtr<T> mSmartPtr<T>::operator()(mSmartPtr<T>& src) {
    return dynamic_cast<??>(src);
}

template <class T>
mSmartPtr<T>::mSmartPtr(T *srcPtr):
data(srcPtr) {
    rc = new RefCount();
    rc->add();
}

template<class T>
mSmartPtr<T>::~mSmartPtr() {
    if (rc->remove() == 0) {
        delete data;
        delete rc;
    }
}


template<class T>
mSmartPtr<T>::mSmartPtr(const mSmartPtr<T> &src):
data(src.data), rc(src.rc) {
    rc->add();
}


template <class T>
T* mSmartPtr<T>::operator->() const {
    return data;
}

template<class T>
T& mSmartPtr<T>::operator*() const {
    return &data;
}

template <class T>
mSmartPtr<T>& mSmartPtr<T>::operator=( mSmartPtr<T> &src) {
    if (this != &src) {
        if (rc->remove() == 0) {
            delete data;
            delete rc;
        }
        data = src.data;
        rc = src.rc;
        rc->add();
    }
    return *this;
}



#endif /* defined(__ProjectManager__mSharedPtr__) */

让我们说我的应用程序包含以下类:

class Base
{
protected:
    ...
public:
    virtual ~Base() =0;
    ...
};


class Derived1 : public Base
{
protected:
    ...
public:
    virtual ~Derived1() {}
    ...
};

class Derived2 : public Base
{
protected:
    ...
public:
    virtual ~Derived2() {}
    ...
};

我需要以下列方式存储数据:

int int main(int argc, char const *argv[])
{
    std::vector<mSmartPtr<Base>> v;
    mSmartPtr<Derived1> d1 = foo();

    v.push_back(d1);

    return 0;
}

我需要以某种方式修复强制转换操作符,但是如何?如何在动态转换中获取基类?

3 个答案:

答案 0 :(得分:0)

在转换方法中提取底层指针并将其转换为新的智能指针。不要忘记复制RefCount并确保您的目标类具有虚拟析构函数(因此无论最后哪个智能指针被处理,都会调用正确的析构函数。)

我无法弄清楚如何在外部定义它,但内联定义有效。

//In the definition, replacing this line
//mSmartPtr<T> operator()(mSmartPtr&)
template<class Tdest>
operator mSmartPtr<Tdest>() {
    mSmartPtr<Tdest> retVal(static_cast<Tdest*>(data));
    retVal.rc = rc;
    retVal.rc.Add();
    return retVal;
}

理论上你还可以添加一个带有r值的版本,如果你使用的是C ++ 11,但我认为这需要做一些工作才能正确完成,所以我避免使用它。

答案 1 :(得分:0)

@Guvante

您的代码无效,我修改如下,但我不知道是否能正常运作

template<class T>
mSmartPtr<T> mSmartPtr<T>::operator ()(mSmartPtr<T>& src) {
    mSmartPtr<T> retVal(dynamic_cast<T*>(src.data));
    retVal.rc = src.rc;
    retVal.rc.Add();
    return retVal;
}

答案 2 :(得分:0)

我认为有更好的选择。除非您有不同的位置,否则您可以通过更改创建对象的方式来避免头痛。

int main(int argc, char const *argv[])
{
    std::vector<mSmartPtr<Base>> v;
    mSmartPtr<Base> d1 = static_cast<Base*>(foo());

    v.push_back(d1);

    return 0;
}

请避免创建与您的矢量输入不同的mSmartPtr