您的位置:首页 > 编程语言 > C语言/C++

C++使用小结(持续更新中)

2008-04-20 22:39 344 查看
每周都留给自己一些看书的时间。孔子说过 学而不思则惘,思而不学则殆

总结:一点模板的小结
1.多个类型型参的实参必须完全匹配
如:compare(short,int)

2.知道什么叫模板类型型参,什么叫实参,什么叫模板非类型型参

3.显式实参

4.类模板成员函数

5.类模板的静态成员

6 类非静态函数指针

class A {
public:
int f( double d ){cout << d << endl; return true;}
};

typedef int ( A::*PFuncOfA )( double d );
PFuncOfA pfunc = &A::f;

7.个建议:

7.1. using的使用

当一个头文件要被他人引用的时候,不建议在头文件中使用using,特别是“using namespace”,因为使用using后,必然会引出一个“名字污染”的问题,在被他人引用的头文件中,这个污染可能是会波及到整个工程。

名字空间本身可以影响using的作用域,所以可以把using放在名字空间中,这样,using的名字只是在这个名字空间中存在;如果using的名字只在某个类中使用,可以使用typedef,那么完全只在这个类中存在。

最好还是不要使用using,因为这个东西,在很多时候和使用名字空间的初衷是相违背的。当代码被他人阅读的时候,可以直接看到名字空间,根据名字空间,可以更好判断当前类的功能、特点……这其中也说明,名字空间名称的定义,也是可以好好斟酌斟酌的。

7.2.类成员变量的保护选择

从结构体到类,最明显的改进就是添加了“private protected public”3种保护。在C++中,struct应该是要被class淘汰的,除了为了兼容。

类成员变量应该都是private,没有必须这么说,但通常绝对是合理的。根据面向对象的思想,一个类的成员就是一个类的一个属性;一个对象的属性如果发生改变,对象必须能够知道,并且进行相应的行为、动作;类的属性可能只是一个简单变量,也可能是通过几个属性合成的,可能今天是简单的,改天就需要改成复杂的。所以,成员的变量使用setxxxx的方法来更改、用getxxxx的方法来获取是非常有意义的。

使用get、set后,再调试的时候可以方便跟踪,可以知道都在什么地方、什么时候你的类的属性被改变了,什么时候被读取了。

一些小细节的建议做法:

1.在循环stl迭代器 的时候 ++使用 ++ iterator,不要使用iterator ++。

2.在一个函数里面用“锁”的时候,并且这个“锁”会锁整个函数调用,用定义临时变量的方式来控制(在临时变量构造时上锁、析构的时候解锁)。

3.当相同的代码出现的不同的地方的时候,将这些代码做成一个函数。

4.如果一个stl的容器需要同步,那么不只是在添加、删除、修改的时候,在遍历的时候也需要。

5.拷贝自己或者他人的代码的时候,一定注意无用的代码和注释,并且整个拷贝过来的代码的作用。

6.当一个类只准备定义一个对象的时候,就把这个类的构造和析构函数定义成私有。

8.实际上程序员在对待其他程序员时候的态度就很好,带着一种挑剔和学习的态度; 但一旦对待自己的代码就很难这么做; 这就是最致命的。程序员也必须对自己的代码带着挑剔和学习的态度; 这个基础是
假设自己的代码是错误的,然后需要做的是怎么样证明自己的代码是正确的。程序员自身可以在程序生成的每个阶段做这些工作:仔细的设计(这个时候画点时间是值得的,必须保证我们对自己的程序有清晰
的轮廓后才能开始动手写)、编写代码时、单元测试(单元测试的重要性就不在赘婿了)、功能测试。

9抛出类类型的异常,而不是指针。栈展开期间,释放局部对象所用内存,运行局部对象析构函数。堆内存则不释放

10.析构函数应该从不抛出异常

11.为捕获的异常,调用terminate,退出程序

12.catch应该从最低派生到最高派生

13.利用auto_ptr做异常释放

14.不能将auto_ptr存储在标准容器中(复制和赋值的关系)

15.虚继承 :用于多继承,实现菱形继承

16.区别指针和引用:前者可以指向空,引用必须总是代表某个对象

17.最好使用C++转型操作符:static_cast dynamic_cast const_cast reinterpret_cast

18.不要以多态方式处理数组 class bst ; class bstchild : bst ; fn(bst array[]); 当传入bstchild arr[10] 时编译器会被误导假设数组中每一个元素大小是 bst

19.++ -- 前置和后置形式:注意前置返回自增后的结果,而后置则是返回旧值 所以:

int i = 0; cout << (i++) << endl; 打印出0;

20 不要重载&& || 和,操作符

21 operator new delete 只能改变编译器new分配的内存,不能改变调用构造函数的流程

placement new :例如: new (buffer) Widget(WidgetSize)

释放: ps->~string() ; delete ps;

22.绝对不要以多态方式处理数组 eg:void fnTest(bstr[] arrBst); bstr如果是类继承关系,函数调用的时候会造成对象大小

23 非必要不要提供默认构造函数(就自己写一构造函数贝,还能累死人吗)

24.以传引用的方式抛异常

try { CT insT; throw insT;}

catch(CT & rCT){} 为啥要抛引用呢,用指针不是更省事,晕,谁保证指针指向的对象啥时候给析构掉 :?为啥不传值呢? 汗,两次拷贝构造挺恶心的。再来个多态调用就挂了

25.了解虚拟继承,不就为了避免菱形继承吗:eg: b->a,c->a, d public b,c,晕,搞了连个a,用虚拟继承吧

26.限制某个类产生的对象数量,HOHO,其实一般使用的是单体,怎么做单体? 构造函数私有化,加一静态变量负责存储唯一的单体。其实这样还不爽,做一单体的模板类,啥类需要用单体,直接引用就ok,Tsingal<***>...

27.智能指针,其实是一挺难搞的问题。std:auto_ptr.用起来挺爽,但一遇到拷贝构造,就发现指针乱飞了,用的时候小心点(不然一个只能指针指向两个不同对象算怎么回事)

哎,还是没很理解,听说boost库提供的智能指针很强悍,找时间看看再回来讨论这话题吧

28.c++要调用c的函数,怎么办? 有办法,在第一函数声明的时候加一extern “C"贝,为啥要这样做呢,只能怪CPP太强呀,支持函数重载,整出的几个函数都同一名字,这不改下函数命名规则不乱套吗。还是C老实点(就是指针有时候给人用得挺恶心的)

29.如果你拷贝的对象中引用了某个外部的内容(比如分配在堆上的数据),那么在拷贝这个对象的时候,让新旧两个对象指向同一个外部的内容,就是浅拷贝;如果在拷贝这个对象的时候为新对象制作了外部对象的独立拷贝,就是深拷贝( 这个一般人都知道)

30.下面是一些模板的使用小结(泛型的东东在stl大量使用,可见有实用的用处)

30.1 多个类型型参的实参必须完全匹配 如compare(short,int)

30.2 知道什么叫模板类型型参,什么叫实参,什么叫模板非类型型参

template <typename T, size_t nSize> class TSingal { TSingal (T& insT);} //T为模板类型型参,nSize为非类型型参

30.3.模板特化:这个挺讨厌的,经常记不住,今天还非得把它记清楚了,嘿嘿:那到底什么叫模板特化:

模板特化是这样一个定义,该定义中一个或多个模板型参的实际类型或实际值是指定的。

特化的形式如下:

关键字template 后面接一对空的尖括号(<>);再接模板名和一对尖括号,尖括号指定这个特化定义的模板型参;

函数型参表;函数体

template<>

int compare<const char*>(const char * &v1, const char * &v2)

{

return strcmp(v1, v2);

}

上面到底特化了什么,就是相比普通的比较模板 一般是 return v1 > v2;(这里是做了指针地址大小的比较),但自从特化成了strcmp做比较,就是指针指向的内容做比较了。oh yeah,这样不就爽多了吗。可以自由组合。

但是有一点限制:特化的声明必须与对应的模板相匹配。类模板的特化也是一个道理,就不写了。

31 类非静态函数指针
class A {
public:
int f( double d ){cout << d << endl; return true;}
};

typedef int ( A::*PFuncOfA )( double d );
PFuncOfA pfunc = &A::f; 这个可以自己写个例子觉悟下,其实无非就是引用类成员函数指针

32. using的使用 下面两个是总部一个老大提的意见,可以琢磨下

32.1. using的使用

当一个头文件要被他人引用的时候,不建议在头文件中使用using,特别是“using namespace”,因为使用using后,必然会引出一个“名字污染”的问题,在被他人引用的头文件中,这个污染可能是会波及到整个工程。

名字空间本身可以影响using的作用域,所以可以把using放在名字空间中,这样,using的名字只是在这个名字空间中存在;如果using的名字只在某个类中使用,可以使用typedef,那么完全只在这个类中存在。

最好还是不要使用using,因为这个东西,在很多时候和使用名字空间的初衷是相违背的。当代码被他人阅读的时候,可以直接看到名字空间,根据名字空间,可以更好判断当前类的功能、特点……这其中也说明,名字空间名称的定义,也是可以好好斟酌斟酌的。

32.2.类成员变量的保护选择

从结构体到类,最明显的改进就是添加了“private protected public”3种保护。在C++中,struct应该是要被class淘汰的,除了为了兼容。

类成员变量应该都是private,没有必须这么说,但通常绝对是合理的。根据面向对象的思想,一个类的成员就是一个类的一个属性;一个对象的属性如果发生改变,对象必须能够知道,并且进行相应的行为、动作;类的属性可能只是一个简单变量,也可能是通过几个属性合成的,可能今天是简单的,改天就需要改成复杂的。所以,成员的变量使用setxxxx的方法来更改、用getxxxx的方法来获取是非常有意义的。

使用get、set后,再调试的时候可以方便跟踪,可以知道都在什么地方、什么时候你的类的属性被改变了,什么时候被读取了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: