我对智能指针比较陌生,如果有人能给我一些提示,让我确认一下我处理智能指针作为类成员的方式是否正确,我将不胜感激。更具体地说,我想在类多态的上下文中实现这个解决方案,并且最好是异常安全的。
给定一个异构对象容器(std::vector> my_vector),通常的添加元素方法是:my_vector.push_back(shared_ptr(new CChild(1))),这样后来可以通过my_vector[0]->doSomething()调用特定派生类的成员函数。
我想实现的目标是将栈对象添加到向量中,同时仍然能够进行多态。直观地说,类似于:
请注意,在我的某些派生类中,我有创建对象的静态成员函数,例如:
在这种情况下,我想知道如何实现一个包含
以下是我想直观实现的示例。首先,我用包含指向派生类的智能指针以及另一个整型成员的
一旦容器被填满,我想执行一些操作,调用每个派生类中专门定制的虚函数,例如
给定一个异构对象容器(std::vector> my_vector),通常的添加元素方法是:my_vector.push_back(shared_ptr(new CChild(1))),这样后来可以通过my_vector[0]->doSomething()调用特定派生类的成员函数。
我想实现的目标是将栈对象添加到向量中,同时仍然能够进行多态。直观地说,类似于:
CChild<float> obj1(1); my_vector.push_back(obj1)
。为了解决这个问题,我现在使用虚构造函数模式:CChild obj1(1); my_vector.push_back(obj1.clone());
。请注意,在我的某些派生类中,我有创建对象的静态成员函数,例如:
CChild<float> obj1 = CChild<float>::initType2(1);
由于要求问题和为了拥有一个清晰的接口,我现在有一个新类CFoo<T>
,它具有作为数据成员的指向CBase<T>
类的智能指针。除了包含其他新的私有成员之外,这个类封装/处理派生对象的智能指针,这样我可以做类似这样的事情:CFoo<float> myfoo(CChild<float>::initType2(1)); my_vector.push_back(myfoo);
。这意味着容器现在是类型vector<CFoo<T> >
,而不是类型vector<shared_ptr<CBase> >
。在这种情况下,我想知道如何实现一个包含
智能指针
作为类成员的类的构造函数?遵循复制-交换惯用法,如何实现operator =
?下面是我设计的一些示例:template < typename T >
class CBase{
public:
CBase(){};
virtual ~CBase(){};
...
virtual CBase<T> * clone() const = 0;
virtual CBase<T> * create() const = 0;
};
template < typename T >
class CChild1 : public CBase{
public:
...
CChild1<T> * clone() const { return new CChild1<T>(*this); }
CChild1<T> * create() const { return new CChild1<T>(); }
static CChild1 initType1(double, double);
static CChild1 initType2(int);
};
template < typename T >
struct type{
typedef std::tr1::shared_ptr<T> shared_ptr;
};
template < typename T >
class CFoo{
public:
CFoo();
CFoo( const CBase<T> &, int = 0 );
CFoo( const CFoo<T> & );
void setBasePtr( const CBase<T> & );
void swap( CFoo<T> & );
CFoo<T> & operator = ( CFoo<T> );
...
~CFoo();
private:
typename type<CBase<T> >::shared_ptr m_ptrBase;
int m_nParam;
};
template < typename T >
CFoo<T>::CFoo()
:m_nParam(0)
// How shall I handle here the "m_ptrBase" class member? e.g point it to NULL?
{
}
template < typename T >
CFoo<T>::CFoo(const CBase<T> & refBase, int nParam)
:m_ptrBase(refBase.clone()), // Is this initialization exception-safe?
m_nParam(nParam)
{
}
template < typename T >
CFoo<T>::CFoo(const CFoo<T> & refFoo)
:m_ptrBase(refFoo.m_ptrBase),
m_nParam(refFoo.m_nParam)
{
}
template < typename T >
void CFoo<T>::setBasePtr( const CBase<T> & refBase ){
// ??? I would like to do sth. like: m_ptrBase(refBase.clone())
}
template < typename T >
CFoo<T>::~CFoo(){
// The memory is going to be freed by the smart pointer itself and therefore
// the destructor is empty, right?
}
template < typename T >
void CFoo<T>::swap( CFoo<T> & refFoo ){
//does this here makes sense?
using std::swap;
swap(m_ptrBase, refFoo.m_ptrBase);
swap(m_nParam, refFoo.m_nParam);
}
template < typename T >
CFoo<T> & CFoo<T>::operator = ( CFoo<T> copyFoo ){
copyFoo.swap(*this);
return (*this);
}
以下是我想直观实现的示例。首先,我用包含指向派生类的智能指针以及另一个整型成员的
CFoo<float>
对象填充容器(请注意,所有这些仅用于说明)。std::vector<CFoo<float> > my_bank;
for (int b=0; b < 3; b++){
float x = b*sqrt(2);
my_bank.push_back( new CFoo<float>( CChild1<float>::initType2(x), b) );
}
for (double s= 1.0; s<= 8.0; s *= 2.0){
my_bank.push_back( new CFoo<float>( CChild2<float>::initType2(x), 0) );
}
一旦容器被填满,我想执行一些操作,调用每个派生类中专门定制的虚函数,例如
doSomething
。for (int i=0; i < (int)my_bank.size(); i++){
int b = my_bank[i].m_nParam;
CBase<float>* myChild = my_bank[i].m_ptrBase;
myChild->doSomething( param1, param2, param3, ..., b);
}
vector
是一个拥有容器,因此您不应该在容器中放置任何自动对象。为什么不先将元素添加到容器中,然后使用该元素代替您原来的自动对象呢?否则,您可以始终插入一份副本:v.push_back(shared_ptr<Base>(new Derived(obj)));
- Kerrek SBDerived(obj)
是什么意思?我如何添加使用“静态函数成员”创建的对象? - TininitType1
或initType2
等静态函数返回的是一个对象而不是指针。所以您建议更改返回类型吗?此外,包装器还包含自己的类成员,而不仅仅是shared_ptr
。根据您的建议,最好的解决方案是考虑vector<shared_ptr<CBase<T> >
,对吗?我想到的是:v.push_back(new CFoo(CChild::initType2(1), 20))。 - Tinstatic
函数成员的知识,因此对于这个天真的代码,似乎需要通过地址返回?就我所寻找的内容而言,它与这个之前的帖子有关。我基本上有一系列具有特定特征的图像滤镜。我需要将每个滤镜应用于特定的图像通道。为了处理这个问题,我需要一个滤镜容器(filterbank)。Foo类将是FilterbankElem类,除了滤镜外还有特定的图像通道。 - Tin