2015-05-29 3 views
1

Я реализовал следующий смарт-класс шаблона указатель: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; 
} 

Мне нужно как-то исправить литой оператор, но как? как получить базовый класс в динамическом броске?

+0

Возможный дубликат [SmartPointer: литой между базовыми и производными классами] (http://stackoverflow.com/questions/5633695/smartpointer-cast-between-base-and-derived-classes) – Guvante

+0

Я пробовал это раньше, это не говоря о литовом операторе, который я ищу, чтобы получить исправление – itorra

+1

Не имеет прямого отношения к вопросу, но, поскольку я был [сказал] (http://stackoverflow.com/questions/28866571/c-multi-index- map-implementation # comment45998667_28866571): имена с двумя ведущими символами подчеркивания зарезервированы для использования в компиляторах и стандартных библиотеках: http://stackoverflow.com/questions/228783 – SU3

ответ

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; 
} 

В теории можно также добавить версию, которая принимает г-значение, если вы используете C++ 11, но я думаю, что это займет немного работы, чтобы сделать правильно, чтобы я избегал его.

+0

Привет, спасибо за ваш комментарий. Как мне можно добавить параметры шаблона в метод класса? – itorra

+0

@itorra: У меня была эта мысль, но я уволил ее. Я обновлю ответ, чтобы включить этот бит. – Guvante

+0

все еще получает ошибки в отношении множества параметров шаблона. – itorra

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; 
} 
+0

Вам нужен еще один параметр шаблона для определения типа ввода или вывода в зависимости от того, как вы его реализуете. К сожалению, я не мог понять, как так переопределить мой, как встроенный. – Guvante

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 что напечатанные иначе, чем ваш вектор.

Смежные вопросы