导语:
在智能指针(一) 中讲解了智能指针的实现方式一,即雇佣一个使用计数类记录共享对象。现在讲解智能指针的另一种实现方式,句柄形式的智能指针。在介绍句柄形式的智能指针之前,先介绍代理类。
代理类:
1、现假设存在一个基类和它的派生类,设计如下:
基类:
class Animal
{
public:
Animal () {
cout << "Create Animal..."<<endl;}
virtual void Name() const {
cout <<"This is Animal..."<<endl;}
virtual ~Animal(){};
};
派生类:
class Cat: public Animal
{
public:
Cat () {cout << "Create Cat..."<<endl;}
void Name() const {cout <<"This is Cat..."<<endl;}
~Cat() {}
};
class Dog: public Animal
{
public:
Dog(){cout<<"Create Dog..."<<endl;}
void Name() const {cout <<"This is Dog..."<<endl;}
~Dog(){}
};
2、若希望用容器或内置数组保存因继承而相关联的对象,例如动物园是一个容器,一个动物园是其中的一个元素,一个动物园的标志就是动物,划分到具体动物就是猫,狗…等。
若定义multiset保存Animal基类类型的对象:
vector<Animal> Zoo;
存在一个Animal标签和一个Cat标签:
Animal ani;
Cat cat;
Zoo.push_back(ani);
Zoo.push_back(cat);
Zoo[0].Name();
Zoo[1].Name();
则加入派生类型Cat的对象时,只将对象的基类部分保存在容器中,派生类对象将被切掉。所以, 容器与通过继承相关的类型不能很好的融合。若派生类属性没有被切掉,Zoo[1].Name()的结果应该是This is Cat… 而实际派生类属性被切掉之后,结果为:
从图中可以看出cat的Name()函数的属性被“切掉”。
3、容器无法保存派生类对象的属性,那么通过容器保存指针是否可行呢?
修改代码如下:
vector<Animal*> Zoo;
Animal ani;
Cat cat;
Zoo.push_back(&ani);
Zoo.push_back(&cat);
Zoo[0]->Name();
Zoo[1]->Name();
打印结果:
结果证明派生类的属性得以保留。原因是采用了