1、避免重复包含
方法:包含保护
实例:
#ifndef Date_H
#define Date_H
Class Date
{
...
...
};
#endif
2、函数动态绑定
作用:通过基类指针或引用来访问基类和派生类中的同名函数。例如通过一个函数通过改变函数参数分别显示基类和派生类的信息。因为函数参数的类型只能是基类才能兼容所有的派生类对象,希望传递派生类对象时能够显示派生类的信息,此时需要通过函数动态绑定来实现。
一个函数实现动态绑定的方法:
1)在基类中该函数被声明为虚函数;
2)函数中引用对象的变量必须包含该对象的地址。
说明:如果一个函数在基类中被定义为虚函数,则在派生类中也默认为虚函数,因此不必在派生类中再加上关节字virtual。
3、静态变量
1) 静态局部变量
当一个函数结束执行后,其所有变量都会销毁,如果希望在下次调用时还能调用局部变量的值,则应当将局部变量声明为静态局部变量。
2)静态数据成员
同一个类的不同对象其数据成员的值是不同的,如果希望多个对象共用同一个数据成员,则应当将该数据成员声明为静态数据成员。静态数据成员属于整个类因此可以通过类名直接访问。
3)静态函数成员
静态函数成员属于整个类,可以通过类名直接访问。静态函数成员没有this指针,只能访问类中的静态数据成员和静态函数成员。如果要访问非静态数据成员和非静态函数成员
4、数学函数
C++中数学函数的实参和返回值都是double型的,如果用整型实参调用数学函数,会导致二义性错误。
5、Debug与Release版本区别
Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
6、良好的编程习惯
1)不要比较浮点数的相等性,因为浮点数是近似的,整数才是准确的。
2)变量在声明时初始化可减少程序的执行时间;
3)编译带有赋值运算符的表达式比编译等价的展开的表达式快,如:c+=3比c=c+3快,因为第一个表达式的c只被分析了一次,而第二个表达式的值被分析了两次。
7、数据类型转换
C语言算术表达式的计算,在计算过程中,每一步计算所得结果的数据类型由参与运算的运算对象决定,相同数据类型的两个对象运算,结果数据类型不变,不同数据类型的运算对象进行运算,结果的数据类型由高精度的运算对象决定。精度的高低:double>float>int
赋值运算要求左值和右值的类型相同,如果类型不同则编译器会进行自动转换,此时一律将右值类型转换为左值的类型。
常数后加小数点就表示浮点数。
两个很大的数据进行运算,其结果在未赋值前编译器会自动分配足够的内存以存储这个值。
8、常量指针
const double *pValue 指针不是常量,但指针指向的数据是常量。因此 *pValue=5是错误的。
double const *pValue 指针是常量,但指针指向的数据不是常量。因此 pValue=&R是错误的。
const double const *pValue 指针和指针指向的数据都是常量。
const 关键字在声明函数参数时特别有用,如果一个值不会改变,应该将其声明为const。
9、动态内存分配
new int 返回的是一个指针。因此动态内存分配需要先声明一个指针。
在声明一个数组的时候,需要指定其元素的个数,当元素个数是变量是就需要动态内存分配。
10、内存泄露
int *pValue=new int;
*pValue=45;
pValue=new int;
保存值45的原内存空间无法再访问,因为已经没有任何指针再指向它,这就导致了内存泄露。
11、assert()
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h>
void assert( int expression );
assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,
然后通过调用通用实用库stdib.h 中的abort 来终止程序运行。
如果定义了符号常量NDEBUG,其后的assert将被忽略。因此如果不再需要assert,那么可以把代码行
#define NDEBUG插入到程序文件中,二无需手工删除assert
12、函数重载
重载的函数必须要有不同的参数列表,不能仅仅依赖于不同的返回类型来重载函数。有时对一个函数调用可能有两个或更多的与之匹配的函数定义,而编译器无法确定哪个匹配更为精准,这就称为二义调用,导致编译错误。
13、构造函数
构造函数是一种特殊的成员函数,其特殊处在于它的名字与类名相同,且没有返回值(不是返回值为空)。
拷贝构造函数是一种特殊的构造函数,除具有构造函数的特点外它还具有形参为本类对象的引用。
如果程序中没有编写拷贝构造函数,系统在用到时会自动生成一个拷贝构造函数,实现对象的克隆。但系统生成的拷贝构造函数实现的是对
对象的浅拷贝,即两个对象共用一段内存。这样会引起一个对象的改变直接导致另一个对象作出相同的改变,更为重要的是如果存在析构函数
会导致一段内存空间会被释放两次从而出现运行错误。
14、析构函数
析构函数的名字也与类名相同但没有任何参数,因此析构函数不能重载。