一、const, enum, inline替代#define
注意:对于单纯常量,用const enum来代替define,而对于宏用inline来实现;
1、 const 与 #define
const 可以定义常量指针;
const可以定义某个类的常量数据成员,实现数据封装;const static实现类的全局数据成员;
2、enum 与 #define
enum更像#define,两者都不可以被引用;如果不想让别人获得一个指针或是引用来指向整数常量,则可以用enum;
3、inline 与 #define
宏定义是函数,但不会引起函数的调用带来额外的开销;
而一个宏完全可以用一个inline类模板实现,且更安全,且不需要在参数上加上括号;
同样可以写出类内的私有inline函数,而宏是不行的;
如
#define A(a,b) (a) + (b)
template<typename T>
inline T fun(const T &a,const T &b)
{
return a + b;
}
二、const
const成员函数里,有时要改变非const成员变量的值,用mutable;
在类里声明成员变量的时候用mutable;这样就指定了哪些值可以改变;
类成员函数如果只是const性的不同,函数可以重载;const对象调用const函数,非const对象调用非const函数;
如果类里用2个相同的函数,仅仅实现的是const之间的区别,则可以这样做:(const版本调用非const版本)
1. 定义一个const函数;
在非const函数里调用cosnt函数;当然要对非const函数的this指针进行类型转换static_cast<const A&>(*a);如果不进行显示的转换,则非const函数会调用它自己! 即会进入无限递归
2. 当返回时,由于const返回的是const值,因此要移除const;用cosnt_cast<T&>(..);
三、确定在使用对象前已经被初始化
之所以用构造函数成员列表,是因为C++规定初始化应该发生在进入构造函数体内之前,因此如果在构造函数体内进行对成员变量赋值,那不是初始化而仅仅是赋值!
class A
{
public:
int a;
A()
{
a = 5; // 赋值非初始化; 先调用默认构造再调用copy构造函数
} // 初始化用成员初始化列表这样效率更高,只调用copy构造
};
如果是const或是引用,则必须是初始化而不是赋值;因此如果用上面的方式是错误的!!!
如果类中有多个构造函数,且有大量的成员变量要初始化,这样就每进行很多重复的操作,因此可以在private里定义一个函数,对这些成员变量赋值,再由构造函数调用;
对于2个不同文件中的类,在一个类中调用另一个类的非本地static对象,是不能确定哪个类被先初始化的,因此可能会问题;因此可以可以设定一个包含另一个类static对象的成员函数,返回该类的引用;
原因是:C++在函数内的本地static对象不是在编译时初始化而是在该函数调用期间首次遇到该对象时初始化;
上面的方法可以应用于A对象要在B之前初始化,而A的初始化受限于B的初始化!
总,初始化做到3点:
1. 手动初始化内置类型
2. 用构造函数初始化列表;
3. 对于不同编译单元的非本地静态对象,用本地函数;用本地static替代非本地static;