Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2115119
  • 博文数量: 249
  • 博客积分: 1305
  • 博客等级: 军士长
  • 技术积分: 4733
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-17 10:37
个人简介

不懂的东西还有很多,随着不断的学习,不懂的东西更多,无法消灭更多不懂的东西,那就不断的充实自己吧。 欢迎关注微信公众号:菜鸟的机器学习

文章分类

全部博文(249)

文章存档

2015年(1)

2014年(4)

2013年(208)

2012年(35)

2011年(1)

分类: C/C++

2013-08-06 21:28:39


    有时候你会想要做这样的安排:让某种类型的对象有“自杀”能力,也就是说能够"delete this"。如此安排很明显要求该类型对象被分配于heap内。另外一些时候你可能想要拥有某种确定性,保证某一类型绝不会发生内存泄露(memory leak),原因是没有任何一个该类型的对象从heap中分配出来。假设你从事嵌入式系统工作,这类系统如果发生内存泄露,是非常麻烦的事情,因为heap空间极其宝贵。我们有没有一些可能完成一些代码,要求或禁止对象产生于heap之中呢?通常可以,但结果证明,所谓的“在heap中”可能比你想象的更含糊。
    
要求对象产生于heap之中(所谓Heap-Based Objects)
    让我们从“限制对象必须诞生于heap”开始。为了严厉执行此等限制,你必须找出一个方法,组织clients不得使用new以为的方法产生对象。这很容易做到。是的,non-heap objects会在其定义时自动构造,并在其寿命结束时自动析构,所以只要让那些被隐式调用的构造动作和析构动作不合法,就可以了。
    欲令这些动作不合法,最直截了当的方式就是讲constructors和destructor声明为private。但这实在太过了,没有理由让它们都成为private。
比较好的办法是让destructor成为private,而constructors仍为public。如此一来,利用条款26所介绍的程序,你可以导入一个pseudo(伪的)destructor函数,用来调用真正的destructor。clients则调用这个pseudo-destructor以销毁它们所产生的对象。
    
    假如,我们希望确保“表现无限精度”的数值对象只能诞生于heap之中,可以这么做:
  1. class UPNumber
  2. {
  3.     public:
  4.         UPNumber();
  5.         UPNumber(int initvalue);
  6.         UPNumber(double initvalue);
  7.         UPNumber(const UPNumber &rhs);
  8.         
  9.         //pseudo(伪的)destructor。这是一个const member function
  10.         //因为const也可能需要被销毁
  11.         void destroy() const
  12.         {
  13.             delete this;
  14.         }
  15.     private:
  16.         ~UPNumber();    //注意:析构函数位于private之内
  17. };
    Clients于是应该这么写:
  1. UPNumber n;                     //错误:虽然合法,但当n的析构函数
  2.                                 //稍后被隐式调用,就不合法了。
  3. UPNumber *p = new UPNumer;        //良好
  4. ...
  5. delete p;                        //错误!企图调用private destructor
  6. p->destroy();                    //良好
    另一个方法就是将所有的constructors都声明为private。这个想法的缺点就是:class常常有许多个constructors,其中包括copy constructor,也可能包括default constructor;class的作者必须记住将它们每一个都声明为private。如果这些函数由编译器产生,编译器产生的函数总为public。
    所以比较容易的办法还是只声明destructor为private,因为一个class只能有一个析构函数。

    只要限制了destructor或constructors的运用,便可阻止non-heap objects的诞生。但是,就如条款26所说,它也妨碍了继承和内含:
  1. class UPNumber
  2. {
  3.     //将constructors或destructor声明为private
  4. };

  5. class NoNegativeUPNumber:         //这是继承
  6.     public UPNumber               //错误!constructors或destructor无法通过编译
  7. {
  8.     ......
  9. };

  10. class Asset                        //这是内含
  11. {    
  12.     private:
  13.         UPNumber value;            //错误:constructors或destructor无法通过编译
  14. };
    这些困难可以克服。令UPNumber的destructor成为protected(并仍保持器constructors为public),便可解决继承问题。
    至于“必须内含UPNumber对象”之classes,可以改为“内含一个指针,指向UPNumber对象”。
  1. class UPNumber
  2. {
  3.     //注意:将destructor声明为protected
  4. };

  5. class NoNegativeUPNumber:         //这是继承
  6.     public UPNumber            //现在没有问题了:derived class
  7.                                 //可以取用protected members
  8. {
  9.     ......
  10. };

  11. class Asset
  12. {    
  13.     public:
  14.         Asset(int initvalue);
  15.         ~Asset();
  16.         .....
  17.     private:
  18.         UPNumber *value;        //..............
  19. };

  20. Asset::Asset(int initvalue):value(new UPNumber(initvalue)) //ok
  21. {
  22.     //......
  23. }
  24. Asset::~Asset()
  25. {
  26.     value->destroy();                    //ok
  27. }


    引自:《More effective C++中文版
























阅读(1665) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~