我想在此将我新学的句柄类做个小结,就我个人理解,C++句柄类的主要目的是在对象层面上实现多态。
比如:
Class A
{
public:
A(){}
~A(){}
virtual void func(){printf("A";}
};
Class B:public A
{
public:
B(){}
~B(){}
void func(){printf("B";}
};
假设现在有一个容器vector<A> vec;
可以这样用:
A a;
B b;
vec.push_back(a);
vec.push_back(b);
但这样做,实际上把b截断了,将b转化为了它的基类A
假如:
vector<A>::iterator iter;
for(iter=vec.begin();iter!=vec.end();iter++)
{
(*iter).func();
}
我们可以看到它们都输出了A;
如何解决这个问题,可以用指针代替对象;如:vector<A*> vec;
这样做可以达到多态的目的,但程序员必须接管内存的管理,例如,
B* b=new B;
vec.push_back(b);
这时假如vec的生命周期结束了,vec不会主动释放b所占用的内存,如果不手动delete b,就会产生内存泄漏
句柄类很好的解决了这个问题,我们可以这样设计
class A{
public:
A(){}
~A(){}
virtual void func() const
{
printf("A");
}
virtual A* clone() const { return new A(*this);}
};
class B : public A
{
public:
B(){}
~B(){}
void func() const
{
printf("B");
}
virtual B* clone() const { return new B(*this);}
};
class sample
{
public:
sample():p(0),use(1){}
sample(const A& a):p(a.clone()),use(1){}
sample(const sample& i):p(i.p),use(i.use){use++;}
~sample(){decr_use();}
sample& operator= (const sample& i)
{
use++;
decr_use();
p = i.p;
use = i.use;
return *this;
}
const A *operator->() const { if(p) return p;}
const A &operator*() const {if(p) return *p;}
private:
A* p;
std::size_t use;
void decr_use(){ if(--use==0) delete p; }
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<sample> vec;
A a;
B b;
sample sample1(a);
sample sample2(b);
vec.push_back(sample1);
vec.push_back(sample2);
vector<sample>::iterator iter;
for(iter=vec.begin();iter!=vec.end();iter++)
{
(*iter)->func();
}
}
我们得到了正确的输出,如同shared_ptr,我们引入了计数,在vec生命周期结束时,我们不需要自己释放内存。
对上面的代码需要注意的是,为什么克隆函数,要用
virtual A* clone() const { return new A(*this);}
而不是直接virtual A* clone() const { return this;}
因为,这样潜在一个问题,比如
B b;
sample sam(b);
vec.push_back(sam);
当b的生命周期结束,而vec的生命周期尚未结束时,调用(*iter)->A.func();就会出错,而更直接的是,这样做与直接用指针进行多态没有太大区别了。