准则
- 对于单纯常量,以const,enum替换#defines;
- 常量定义式常被放到头文件内,以便被不同源码含入
- 对于形似函数的宏(macros),改用inline函数替换#defines
- 对于class专属常量,为了确保常量至多有一份实体,必须成为一个static成员(单例模式)
- 例子
//只是声明,如果不取变量地址,可以不提供定义式,
//但是如果要取某个专属变量的地址,编译器需要您提供定义式:
static const int m_num = 5;
//note:总是为为静态变量提供定义,可以避免出错。
//定义式
const int 类::m_num; //放入实现文件,不能重复赋值
//如果你的类中如数组大小要用到专属常量的值,则使用
enum{m_num = 5}; //m_num是5的·一个记号名称,类似#define,但有封装性,和#define一样取址不合法。
enum、static
实现编译期间就要知道数组的大小功能
//实现编译期间就要知道数组的大小功能
class GAmePlayer
{
private:
static const int NumTurns = 5;//常量声明式,还未定义!static要在类外定义(最好总是提供定义)
int scores[NumTurns];//使用该常量
};
const int GAmePlayer::NumTurns;//声明时已经有了初值,定义时不能有了,会报错。
//也可以利用nums实现
class GamePlayer
{
//enum理解为记号
enum {NumTurns = 5};//令NumnTurns成为5的记号
int scores[NumTurns];
};
const
准则:离什么近就表示什么不可变
- const T * t表示被指物T不可改变
- T * t const 表示指针t不可改变
- const T * t const指针和被指物均不可改变.
const vector<typename>::iterator iter;
内容*iter可以变vector<typename>::const_iteraror cIter;
内容不可变
- 非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编译错误),标记该函数可以作用于const对象,表示成员函数隐含传入的this指针为const指针,决定了在该成员函数中, 任意修改它所在的类的成员的操作都是不允许的;
- 两个成员函数如果只有常量性不同,也是可以被重载的!只不过使用的时候要用const区分
- 变量声明为mutable后,即使在const成员函数内,也可能总是被修改!
- 加了const的成员函数可以被非const对象和const对象调用
但不加const的成员函数只能被非const对象调用
#include<iostream>
//两个函数如果只是常量性不同,可以被重载
class TextBlock
{
private:
string text;
public:
//const不同也能重载
const char& operator[](size_t position) const { return text[position]; }
char& operator[](size_t position) { return text[position]; }
};
//使用
const TextBlock ctb("World");
cout << ctb[0];
ctb[0] = 'x;'//错误!试图写一个const类型变量
TextBlock tb("Hello");
cout << tb[0];
tb[0] = 'x';
note:
如果函数的返回类型是个内置类型,改动函数返回值是不合法的。
non-const operator[]
的返回类型是个reference to char
,不是char
,如果是,tb[0] = 'x'
通不过编译!(返回引用和返回类型的区别!,见如下代码)
#include<iostream>
using namespace std;
string make_plural(size_t,const string&,const string&);
const string &shorterString(const string &,const string &);
const string &mainip(const string&);
char &get_val(string &,string::size_type);
int main(void)
{
cout<<make_plural(1,"dog","s")<<endl;
cout<<make_plural(2,"dog","s")<<endl;
string string1="1234";
string string2="abc";
cout<<shorterString(string1,string2)<<endl;
cout<<mainip("jiajia")<<endl;
string s("123456");
cout<<s<<endl;
get_val(s,0)='a';
cout<<s<<endl;
getchar();
return 0;
}
//返回非引用
string make_plural(size_t i,const string &word,const string &ending)
{
return (i==1)?word:word+ending;
}
//返回引用
const string &shorterString(const string &s1,const string &s2)
{
return s1.size()<s2.size()?s1:s2;
}
//禁止返回局部对象的引用(我的dev c++ 没有报错,比较可怕)
const string &mainip(const string &s)
{
string ret=s;
return ret;
}
//引用返回左值
char &get_val(string &str,string::size_type ix)
{
return str[ix];
}
inline
- 类内定义,默认为内联函数
- 类外的内联函数要显式加
inline
犯过的缺陷语句:无论什么时候你写了像这样的宏,你必须记住在写宏体时对每个参数都要加上括号#define max(a,b) ((a) > (b) ? (a) : (b))
替代:以用普通函数实现宏的效率,再加上可预计的行为和类型安全,这就是内联函数
inline int max(int a, int b) { return a > b ? a : b; }
//进一步改进,实现对不同类型
template<class T>
inline const T& max(const T& a, const T& b) //因为不知道T的类型,返回时传递引用可以提高效率
{
return a > b ? a : b;
}