向往的程序人生

C,C++,设计模式,3D图形学,游戏开发
posts - 4, comments - 13, trackbacks - 0, articles - 0

C++编程中的一些感悟

Posted on 2009-04-23 15:44 向往 阅读(1004) 评论(4)  编辑 收藏 引用 所属分类: C/C++/Script
接触C++已经有五个年头了,多多少少在学习和工作的过程中有些感悟,遂一一记录,勉己勉人.
有少许字段是摘抄自网上的文章,但存档时只是随手黏贴,丢失了作者信息,无法列出,对此表示歉意,并感谢发扬分享精神的原作者.
此外,若以后有新的感悟将在此添加.有不当之处,恳请指正.
  1. 指针赋值时,要谨防指针的同值性.如:
     1 void SharePtr::operator = (Ptr *ptr)
     2 {
     3     if(mPtr != ptr)        // 防止指针同值.其中mPtr是SharePtr类中用来保存指针的变 量.
     4     {
     5         if(mPtr != NULL)
     6         {
     7             delete mPtr;   // 如果不是同值, 删除之前的指针.
     8             mPtr = ptr;
     9         }
    10     }
    11 

  2. 不要忽视编译警告,有些警告是出现bug并导致程序crash的征兆。比如类型转化警告、数据未初始化警告都可能导致程序出错。为了以后减少调试和避免错误的几率,请重视编译器的警告信息。
  3. 当工程需要给Class加导出前缀(如:__declspec(dllexport))却有些没有加时,其他工程引用它将会出现 Unrezosle Symbol的错误.
  4. 若某个类需要作为父类,其析构函数必须声明为virtual,否正子类的析构函数无法调用,导致内存泄漏.
  5. 新增一个Class时,先定好接口,然后再编码.这样可以不用经常改动,减少编译时间. 
  6. 要谨防数值越界.对于有些存储范围小的变量,必须先进行越界处理,然后再赋值.如:
    // 未添加数据越界检测代码
    int num = -1;
    unsigned 
    char ch = num; // ch的值不是-1,而是255.因为num超出了unsigned char表示的范 围.

    // 添加了数据越界检测代码
    int num = -1;
    assert(num 
    >=0 && num <= std::limit<unsinged char>::max());  // 若越界则弹出断言
    unsigned char ch = num;
  7. 在宏里边尽量不定义变量,否则在外部调用两次时,有可能出现变量重复定义的错误.
    如果确实要定义变量,可以改写成函数.
  8. 不要为模式而模式.使用设计模式只是为了更好地复用和扩展,如果得到反作用,宁愿不用.
  9. 有些子类应当覆盖抽象类vitual成员时,千万不能误写为重载.否则很难查出错误.
  10. 若有两个人做同一个模块时,需要商量好整体架构,明确分工,不可随意修改他人的代码,若要修改也应告诉原作者.若对某些分工意见有分歧时,应慢慢磨合,耐心心细比较,确定可行方案,切不可逃避,将问题延续下去. 
  11. 定义接口时,尽量为使用者(用户)提供明朗,统一,清晰的接口:
    1) 尽可能使用默认参数;
    2) 使用管理器管理物体的创建删除;
    3) 使用抽象类抽象出若干类似Object的接口;
    4) 函数名尽量使用动词或动宾结构,并体现出职责;
    5) 在实现相同功能的情况下,对外提供的函数应尽可能少;
    6) 能声明成private或protected的数据成员和成员函数就不要声明为public. 
  12. 每个对象应当完成并且只完成它该做的事,只管它该管的事,简而言之,就是对象内部,对象之间应该保持"高内聚,低耦合".
  13. 写一个循环时,如果该循环体比较大,则应该先写好循环判断条件,再实现细节.
    while(i > 0)
    {
        
    --i;
    }
    //实现如上代码后,再写实现细节(循环体).这样做的目的是可以避免在实现细节后忘记增加--i等这类循环因子更新语句.
    如:while(i > 0)
    {
        循环 体;
        
    --i;
    }
  14. 代码中的注释应当致力于解释为什么,而不是怎么做。好的注释并不是重复代码中显而易见的事实,而是引起对代码中微妙的弱点的重 视。明白的代码常常是被注释所玷污了,不过对于作者显而易见的东西对于读者来说常常是晦涩的。一整段的注释要比逐行解释好的多。
  15. 类的组织Class organization
    1).按照以下顺序组织类的定义,按照用户最为关心的顺序组织类的代码:
    Public type forward-declarations & typedefs  
    Public constructors & destructor  
    Public member functions
    -----------------------------------------------------------
    Protected type forward-declarations & typedefs  
    Protected member functions  
    -----------------------------------------------------------
    Private type forward-declarations  
    Private member functions  
    Private data members  
    2).尽量不要在类的定义体中进行函数定义。模板及内联函数除外。
    3).复用public private protected关键字,将不同类型的成员分开,如成员函数和数据成员。
    4).在继承类里就不要重复写virtual关键字,可以 将它们的声明组织成一组。
  16. 在使用new/delete, malloc/free时,注意"谁创建谁销毁"的原则.除非有明确的规约,否则很容易造成内存管理混乱,导致出现内存错误.
  17. 头文件包含其实是一想很烦琐的工作,不但我们看着累,编译器编译的时候也很累,再加上头文件中常常出现的宏定义。感觉各种宏定 义的展开是非常耗时间的,远不如自定义函数来得速度。我仅就不同头文件、源文件间的句则结构问题提出两点原则,仅供参考:
    第一个原则 应该是,如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没 有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。
    第二个原则应该是,尽量在 CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并便宜成功,那么在A的实现 中我们需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H文件)。
  18. 解决头文件相互包含问题的方法之一:在.h文件里用class A声明,数据成员用指针或者引用,在.cpp里用#include"A.h"即可.
  19. 在索引列表时,最好能根据索引和名字来获取元素,以满足不同场合的需求.在编辑器制作中更彰显其意义.
  20. 在类A的构造函数里如果有类B成员变量b,并调用了b的某个函数如b.fun(),则b.fun()里边不能调用A的指针.因 为此时A的指针尚未完成空间分配,强行调用将导致出错.
    这种情况在Debug下偶尔出错,但在Release版下一定出错.应当引起 重视!
  21. 以二进制存储信息时,要注意int等类型在不同的平台不同CPU架构下长度是不一样的,故在写入文件时,建议先用宏 (如#define INT_LENGTH 4)来表示写进文件的长度.此外,还要注意字节序(高位在前还是低位在前)的问题.
    所以一般情况下,用文本文件来存储相关信息,避免 了那些问题.
  22. 由于std::vector里边的内存管理机制会适时释放内存以调整合适的大小,故在外部不要保存std::vector里的 元素地址.如果确实要保存,则每次增删vector元素时必须更新外部的指针,否则将可能造成垃圾指针而出现内存错误(有时候甚至不报错,程序运行出现不 可预料的结果.很诡异,很难发现bug).
  23. 永远不要在类的构造或者析构过程中调用虚函数,因为这样的调用永远不会沿类继承树往下传递到子类中去。否则很有可能出现很隐晦 的bug.参见:http://www.enet.com.cn/article/2005/0706/A20050706431501_2.shtml
  24. 给有虚函数的模板类添加父类.即将公用接口抽象在父类里,就可以统一处理模板类了.

Feedback

# re: C++编程中的一些感悟  回复  更多评论   

2009-04-23 18:22 by Sunshine Alike
好文!学习了~~

# re: C++编程中的一些感悟  回复  更多评论   

2009-04-24 01:31 by sisco
感觉像大杂烩,不过有些条目精辟入里.谢谢!

# re: C++编程中的一些感悟  回复  更多评论   

2009-04-24 11:28 by 向往
@Sunshine Alike
@sisco
如果本文对大家有所帮助,是我写文章的初衷和动力.谢谢赏阅.

# re: C++编程中的一些感悟  回复  更多评论   

2009-08-21 22:43 by 李现民
第六条,比较好

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理