条款二——使用const,enums,inline 替换#define
变量使用 const,enums 替换define
函数使用 inline 替换define
define 会在预处理阶段进行替换,程序的可读性会很差
思维导图
const替换define
特殊情况一
当需要将指针放到头文件
中方便其他文件使用,必要时将指针声明成常量指针+指针常量的形式: const char* const sp = "adsf"
,这种情况下可以使用const string sp("asdf")
进行替换
特殊情况二
需要在类内
使用一个常量定义数组
时,可能需要一个class专属的常量
进行定义
方法一: 可以使用define在类中定义常量
使用,并在使用完之后立即#undef
,就可以满足在一个类中定义常量的需求(默认使用#define是全局可见的,所以需要使用#undef来限制作用域
)
方法二:
需要先明确什么类型的变量能定义数组大小
——static const 变量
在全局中定义一个const变量也是可以定义数组大小
——全局变量存储在静态区中,相当于默认就是静态变量
class A
{
public:
static const int NUM = 5;
int _nums[NUM];
};
//const int A::NUM = 5;
同时可以使用enum代替define
达到既在类内,又能定义数组的目的
enum { NUM = 5 };
int _nums[NUM];
使用inline替换define函数
先看一个经典案例
这中代码看起来就很坑,而且很不好调试
可以使用inline
进行替换,而且inline拥有函数作用域的特性
,同时也一定程度上拥有define在预处理时被替换的特性
(inline更像是一种建议,建议编译器替换,对于较长的代码是不会进行替换的)
template<class T>
inline void fun(T a, T b)
{
f((a) > (b) ? (a) : (b));
}
写成这个样子,更安全
条款三——尽量使用const
思维导图
int* + const
#include
using namespace std;
int main()
{
// const + int* 的基本使用
int a = 10;
const int* pa = &a;// 常量指针常量不可改——不能*pa = 20;
int const* pb = &a;// 同上,只有写法不同
int* const pc = &a;// 指针常量指向不可改—— 不能 pb = pa
const int* const pd = &a;// 常量指针+指针常量——既不能 pd = pa;又不能*pd = *pa
return 0;
}
iterator,const_iterator,const iterator的区别
iterator——int*
const iterator ——int* const 指针常量
,指向不可改
const_iterator —— const int* 常量指针
,内部变量不能改变
降低用户使用时带来的错误
需要修改内部const成员
当需要使用const 实例修改内部变量时
使用mutable
关键字来修饰,用来释放non-static的const 约束
——可以让他再const实例中进行修改
class A
{
public:
void fun(int a) const
{
_a = a;
}
mutable int _a;
};
int main()
{
const A cona;
cona.fun(10);
cout << cona._a << endl;
cona.fun(20);
cout << cona._a << endl;
return 0;
}
const和non-const成员函数避免重复
const 和non-const成员函数一般实现都是一样的
,只有调用函数的实例的属性不一样,作为程序员尽量避免
写出这种重复的代码
class A
{
public:
const int& operator[](const int p) const
{
return _nums[p];
}
int& operator[](const int p)
{
return _nums[p];
}
int _nums[100];
};
使用const函数调用non-const函数
class A
{
public:
const int& operator[](const int p) const
{
return _nums[p];
}
int& operator[](const int p)
{
// const_cast , T 只能是引用,指针,指向成员类型的指针
return const_cast<int&>(static_cast<const A&>(*this)[p]);
}
int _nums[100];
};
static_cast —— 普通的类型转换
const_cast —— 去除const属性
static_cast —— 将*this 从原始类型 A&
转换为cosnt A&
const_cast —— 完成const 向 non-const 安全转换
不能再non-const内部直接调用operator[],这样会无限递归下去,也就是自己调用自己
不能使用const 调用 non-const (可能在调用non-const函数的内部对数据进行改变,很危险)