[cpp] Присваивание умных указателей
Шаблон нельзя унаследовать от другого класса?
Скажем, есть CSmartPtrVoid, и шаблон class CSmartPtr<T> : public CSmartPtrVoid
Можно-можно
Или в указателе описать присваивание шаблоном по двум типам - но это сработает для любой пары типов.
template <class T> class CTest
{
public:
CTest(T t)
{
m_T = t;
}
T m_T;
template <class T2> CTest<T>& operator=(CTest<T2> src)
{
std::cout << "inside operator=" << std::endl;
m_T = src.m_T;
return *this;
}
};
Ну да, все правильно. А в m_T = src.m_T действует обычный плюсовый контроль типов + dynamic_cast.
CSmartPtrVoid не соддержит информации о типе данных (Т как мне его использовать в присваивании?
Другие варианты, как я понимаю, требуют в явном виде указать какие у Т1 наследники есть. Это сделать можно, но не хотелось бы..
CTest<int> t1;
CTest<double> t2;
t1 = t2;
Ну или для твоего варианта:
class A{ };
class B: public A { };
.....
A a;
CTest<A> t1(a);
B b;
CTest<B> t2(b);
t1=t2;
(t2 = t1; писать нельзя)
Еще тупой вопрос: можно ли избежать необходимости делать m_T public?
T& GetT { return m_T; }
void SetT(T t) { m_T = t; }
...
SetTT)src.GetT;
Но тогда при вызове SetT будет создаваться новый экземпляр класса. Этого можно избежать если писать SetT(T& t но будет работать только для родственных классов.
Ещё можно сделать через указатели:
void SetT(T* t) { m_T = *t; }
T* GetT { return &m_T; }
...
SetTT*)src.GetT;
Просто посмотри исходники std::auto_ptr или boost::shared_ptr. А то тебе сейчас тут навпаривают...
У auto_ptr логика работы другая - destructive copy, мне не подходит. А в shared_ptr очень похоже на то, что предложил , но требуется компилятор получше моего VC6. Для VC6 там очень простая схема, где мой вопрос остается без внимания.
Всем спасибо!
ИМХО, необходимость таких извращений зачастую означает неправильный подход к решению поставленной задачи.
Ситуация очень проста: был проект с некоторой иерархией классов, где никаких умных указателей не было. Захотелось их туда прикрутить, тут-то и возникли проблемы. Конкретный вопрос с присваиванием возник, когда надо было хранить в одном контейнере указатели на разные родственные объекты.
И стандартные смарт поинтеры тебя не устраивают чем?..
Уже описал выше.
std::auto_ptr<B> pB(new B;
std::auto_ptr<A> pA;
pA = pB;
у этого пойнтера поведение отлично от того, что требуется
Насколько я понимаю, после pA = pB; pB уже не будет ссылаться на нужный объект. Это не то, что мне надо.
Проблема в том, что если делать
CSmartPtr& operator=(const CSmartPtr<T> &sp)
то он не вызывается - ведь справа все-таки другой тип.
template<class S>
CSmartPtr& operator=(const CSmartPtr<S> &sp) {
this->_p = sp._p; //compiles only if S extends T
//increment ref count...
}
Спасибо. Именно это предложил , и именно так я уже и сделал. Работает.
Оставить комментарий
karkar
Пусть есть шаблон умного указателя CSmartPtr<T> с подсчетом ссылок.Пусть есть тип T1 и наследный от него T2. Есть два умных указателя CSmartPtr<T1> p1 и CSmartPtr<T2> p2. Как описать оператор присваивания, чтобы делать p1 = p2?
Проблема в том, что если делать
CSmartPtr& operator=(const CSmartPtr<T> &sp)
то он не вызывается - ведь справа все-таки другой тип.
А если
CSmartPtr& operator=(T* p)
то срабатывает (т.к. есть оператор T*) но теряется информация о счетчике ссылок.