C++对象的生死

我在设计一个类时最先考虑的是对象的生命周期和上下文. 简单来说就是: 对象由谁在什么时候new出来, 又由谁在什么时候delete掉. 因为C++没有垃圾回收, 所以不得不考虑这些问题. 虽说拿Java来做就没有这些烦恼, 但思考这些问题会让我更明白这个类的代表着什么, 如何更好的设计.

假如, 现在要设计一个显示器类, 类的名字就要Display好了. 其基本功能是开关显示器, 查询显示器的参数, 例如尺寸大小, 分辨率, 点距等等.

实现如下:

   1: class Display { 
   2: public: 
   3:     Display(const char* display_name); 
   4:     ~Display();
   5:  
   6:     // contorl functions 
   7:     void turnOn(); 
   8:     void turnOff();
   9:  
  10:     // info functions 
  11:     int pixelWidth() const; 
  12:     int pixelHeight() const; 
  13:     // ... 
  14: };
控制接口和查询接口的意义都很明确, 但是上面构造函数和析构函数就有歧义了.
构造函数接受一个显示器的名字来创建显示器(比如你有多个显示器或者远程显示器).
   1: Display* d = new Display("0");
   2: // ...
   3: delete d;
"new"出一个显示器是什么意思. 显示器就在那干嘛要"new", "new"一个显示器我会多一个显示器吗? ''delete"显示器也说不通吧. 
好吧, 有人会说我这是咬文嚼字, 但正是这种咬文嚼字让我以另一个方式来理解: 把Display对象当做一个可以操作显示器的"句柄"对象. "new"只是创建一个用于操作显示器的句柄而已, 显示器还是显示器.
说到句柄, 首先想到的肯定是Windows里面的句柄. 一样地, 句柄是对设备资源的引用, 通过句柄可以操作设备, 但不能通过句柄"delete"设备. 这点比指针安全多了.
so, 我们要设计的显示器类要分成两部分了, 一个是操作的句柄DisplayHandle, 另一个是真正对应显示器的类DisplayDevice. DisplayDevice是一直都存在的, DisplayHandle构造出来后就连接上一个DisplayDevice.
   1: class DisplayHandle {
   2: public:
   3:     DisplayHandle(const char* display_name)
   4:             : m_device(DisplayDevice::GetDisplay(display_name)) {
   5:     }
   6:  
   7:     // control functions
   8:     void turnOn() {
   9:         m_device->turnOn();
  10:     }
  11:     void turnOff() {
  12:         m_device->turnOff();
  13:     }
  14:  
  15:     // ...
  16:  
  17: private:
  18:     DisplayDevice* m_device;
  19: };
  20:  
  21: class DisplayDevice {
  22: public:
  23:     static DisplayDevice* GetDisplay(const char* display_name);
  24:  
  25: private:
  26:     DisplayDevice();
  27:     ~DisplayDevice();
  28: };
DisplayDevice是内部的类, 不会暴露出来, 用户也拿不到DisplayDevice的指针. 这比之前Display的概念就清楚多了: "new"出一个Display(DisplayHandle)只是连接了显示器设备, 获得了控制权, 这个对象的生死和显示器没有任何关系.
另一个关于对象生死的例子就是窗口控件.
首先, 控件对象创建出来, 窗口就应该有(假设不隐藏). 窗口关闭, 控件对象就应该销毁(复杂点).
再者, 父控件销毁了, 子控件也应该全部销毁. 原因是父窗口关闭了, 子窗口也应该都关闭, 自然地子控件控件都要销毁.
所以说, 设计窗口控件时一定不能让控件对象在栈上创建; 因为控件对象的生命周期和窗口一样, 其生命是交由用户来决定的, 而不是靠栈来管理的.
很多窗口控件库都是这样设计的, 这里就不举例了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值