问题:设计一个容器类,可以装载相关联的类。
一般容器类如vector或是list只能存放相同类型的类。这里我们想实现类似如下的功能:
VehicleSurrogate parking_lot[100];
Trunk x;
parking_lot[0] = x;
Car c;
parking_lot[1] = c;
如果parking_lot存储的是指针,相对而言会容易的多,不过考虑到指针存储就有释放的问题,管理起来会很复杂,先不考虑。
解决方案:
通过设计一个抽象基类,所有关联类从此抽象类继承,然后使用一个代理来表示具体的类实例。如用vehicle表示抽象的交通工具,用start表示这些交通工具共同的能力:用car,trunk表示具体的交通工具,轿车,卡车。VehicleSurrogate用来表示具体的轿车,卡车。
1 设计相关联的类
// 头文件定义 Vehicle.h
class Vehicle
{
public:
virtual double weight()const = 0;
virtual void start() = 0;
virtual Vehicle* copy() const = 0;
virtual ~Vehicle() {}
};
class Trunk :public Vehicle
{
public:
Trunk();
virtual double weight() const;
virtual void start();
virtual Vehicle* copy() const;
private:
double _weight;
};
class Car : public Vehicle
{
public:
Car();
virtual double weight() const;
virtual void start();
virtual Vehicle* copy() const;
private:
double _weight;
};
// 实现文件 Vehicle.cpp
Trunk::Trunk()
{
_weight = 20;
}
double Trunk::weight() const
{
return _weight;
}
void Trunk::start()
{
cout << "I'm Trunk,weight:"<<weight()<<".I start." << endl;
}
Vehicle* Trunk::copy() const
{
return new Trunk(*this);
}
Car::Car()
{
_weight = 5;
}
double Car::weight() const
{
return _weight;
}
void Car::start()
{
cout << "I'm car,weight:" << weight() << ".I start." << endl;
}
Vehicle* Car::copy() const
{
return new Car(*this);
}
至此,创建了两种具体的交通工具,trunk和car,他们都可以克隆出自己。
下面用代理类来装载这些具体类。
class VehicleSurrogate {
public:
VehicleSurrogate();
VehicleSurrogate(const Vehicle &);
VehicleSurrogate(const VehicleSurrogate &);
VehicleSurrogate &operator=(const VehicleSurrogate &);
//来自类Vehicle的操作
double weight() const;
void start();
private:
Vehicle *vp;
};
VehicleSurrogate::VehicleSurrogate()
:vp(0) {}
VehicleSurrogate::VehicleSurrogate(const Vehicle &v)
: vp(v.copy()) {}
VehicleSurrogate::VehicleSurrogate(const VehicleSurrogate &vs)
: vp(vs.vp ? vs.vp->copy() : 0) {}
VehicleSurrogate &VehicleSurrogate::operator=(const VehicleSurrogate &vs)
{
if (&vs != this)
{
delete vp;
vp = (vs.vp ? vs.vp->copy() : 0);
}
return *this;
}
double VehicleSurrogate::weight() const
{
if (vp == 0)
throw "abc";
return vp->weight();
}
void VehicleSurrogate::start()
{
if (vp == 0)
throw "abc";
return vp->start();
}
至此,定义VehicleSurrogate parking_lot[100]后,已经可以装载具体的交通工具卡车和轿车了。
在进行:
Trunk x;
parking_lot[0] = x;
实际上是用到了赋值函数VehicleSurrogate &operator=(const VehicleSurrogate &);
从而实现了将不同的类赋给容器
附测试代码:
#include "stdafx.h"
#include <iostream>
using namespace std;
#include "VehicleSurrogate.h"
int main()
{
int num_vehicles = 0;
VehicleSurrogate parking_lot[100];
Trunk x;
parking_lot[0] = x;
Car c;
parking_lot[1] = c;
parking_lot[0].start();
parking_lot[1].start();
return 0;
}