尽量用const ,enum和inline 而不用#define(尽量用编译器而不用预处理),以及返回引用的知识点

准则

  1. 对于单纯常量,以const,enum替换#defines;
  2. 常量定义式常被放到头文件内,以便被不同源码含入
  3. 对于形似函数的宏(macros),改用inline函数替换#defines
  4. 对于class专属常量,为了确保常量至多有一份实体,必须成为一个static成员(单例模式)
  5. 例子
//只是声明,如果不取变量地址,可以不提供定义式,
//但是如果要取某个专属变量的地址,编译器需要您提供定义式:
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

准则:离什么近就表示什么不可变

  1. 普通的const

  • const T * t表示被指物T不可改变
  • T * t const 表示指针t不可改变
  • const T * t const指针和被指物均不可改变.
  1. STL的const:修饰迭代器

  • const vector<typename>::iterator iter;内容*iter可以变
  • vector<typename>::const_iteraror cIter;内容不可变
  1. const成员函数(相对应mutable:可变的)

  • 非静态成员函数后面加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; 
}

猜你喜欢

转载自blog.csdn.net/vict_wang/article/details/85763265
今日推荐