C++读《C++沉思录》有谢

至于类的宏图:代理类

《C++沉思录》的原话是这么的

咱们怎样才能设计一个C++容器,使它发出力量包含类型不同而互相相关的目标也?

咱们从胡要这样一个容器开始谈论。

比方我们设规划一个停车场,这个停车场即是一个容器。那么停车场需要停止各种不同的车辆,不同之车子即是例外的类似,但她们都是产生关联的(都是通行器)。我们掌握,C++标准的容器中存储的且是千篇一律档次的类似,例如数组,vector……那么旧的容器就无法满足我们停车场的需求了。
所以我们即便需一个克包含类型不同而相互相关的目标(车)

脚我们来效仿整个工艺流程

  • 当发出停车场之前,要事先有车。因此,首先得一个虚无基类,命名吧Vehicle。它发同一层层之派生实类:Automobile,Truck……

class Vehicle{ 
public:
           virtual double weight() const = 0;
           virtual void start() = 0;
           // ...
};
class Automobile: public Vehicle {/*...*/};
class Truck: public Vehicle {/*...*/};
......

  • 而今咱们来学停车场(容器)。这个停车场到底得什么力量吗?
    (1)停车场实际上是免欲知道到底是什么车停进的,只待掌握她是车。
    (2)有车进入的时节,我们能够跟她,给一个车位(内存)给它们。
    (3)车换位置停的时光,我们要懂得其换到啊了。
    (4)当车离开的时段,我们如果管车位(内存)释放。
    咱们便的做法是故一个指针数组

Vehicle* parking_lot[1000];
Automobile x = /*.....*/;
parking_lot[num_vehicles++] = &x;
//num_vehicles means numbers of vehicles

这样做有一个弊端,这个指针是直指向车本身的。打只假设,假如车开有了停车场,理论及来说,这个指针还见面随着车走,但自身之指针是属于停车场的,出非失,那么车起出去的上是指针指于哪里就out of control

既这样,那我们来举行第一个转移。我们不被指针指于车自,我们赖以为其的一个副本。

Automobile x = /*.....*/;
parking_lot[num_vehicles++] = new Automobile(x);

自我大概解释一下第二执等号右侧代码的意思:new操作符分配了相同块内存(车位),返回指为这块内存的指针,大小也Automobile这么大;Automobile(x)举凡一个复制构造函数,返回值是一个与x一样的切近。
这做法时有发生少数单弊端:1. 增显示动态内存管理的承担。2.
自我用适量知道它是啊项目。

但实际上,停车场并不需要它到底是啊款车型,只要掌握出车进入就是实行了。


要是代码是这样的,就特别简单了

Automobile x = /*.....*/;
parking_lot[num_vehicles++] = x;

免欲展示的处理内存,不需要判定车之花色。


怎么样就既能够免显示的拍卖内存分配,又会保障类似以运转时绑定的性质也?
缓解此问题的重大是如果之所以接近来表示概念,这在C++中是格外常见的。我接连将立即一点当作最基本的C++设计规范。在复制对象的历程中运用是计划原则,就是概念一个作为及Vehicle对象一般,而还要神秘兮兮的意味了装有继续自Vehicle类的目标的物,我们管立即路的对象叫做代理(surrogate)

言到此处,相信大家还应该知道,实际上,停车场需要操作的实际是车位,并无是车。车位,是一个以及车辆绑定的事物。在这例子中,我们得管车位理解成车辆类的代理。


不管第一栽变通办法还是定义代理,我们还亟需一个操作,就是复制copy(),因此,我们要创新一下车辆类的定义

class Vehicle{ 
public:
           virtual double weight() const = 0;
           virtual void start() = 0;
           virtual Vehicle* copy() const = 0;
           virtual ~Vehicle() { }
           // ...
};

Vehicle* Automobile::copy() const{
          return new Automobile(*this);
}
......

发出矣虚函数copy来就复制工作,那么代理类(车位)就比较好写了:

class VehicleSurrogate{
public:
          VehicleSurrogate();
          VehicleSurrogate(const Vehicle&);
          ~VehicleSurrogate();
          VehicleSurrogate(const  VehicleSurrogate&);
          VehicleSurrogate& operate=(const VehicleSurrogate&);
          //来自类Vehicle的操作
          double weight() const;
          void start();
          //...
private:
          Vehicle* vp;
}

值得注意的凡,在代理类(车位)中,我们重载了赋值符‘=’。目的是为持续代码的凝练。(上述代码只叫有了定义,具体落实比较简单,需要之私聊)


完了了上述的行事,我们的停车场中心就格外轻定义了。

VehicleSurrogate parking_lot[1000];
Automobile x;
parking_lot[num_vehicles++] = x;

末尾一行代码的原型是:
parking_lot[num_vehicles++] = VehicleSurrogate(x);
我们重载的赋值符 ‘=’ 的便宜就是涌出了,使代码变得越来越简洁明了。


末尾,当然如果覆盖下伏笔啦。什么伏笔为?
信任细心之读者也意识,涉及到代办就去不开复制,但是复制一个近似的代价有时候是深非常的,是咱无乐意的开发的,那我们如何避免这些复制呢?希望读者为会考虑思考。