effective c++条款03

const这个关键字非常的神奇,我们首先来剖析它的作用
它的作用范围类外可以修饰global或者namespac作用域中的常量,也可以修饰文件,函数,或者区块作用域中被声明为static的变量 或者修饰指针,或者修饰函数
在class内可以修饰内部的static或者non-static变量,成员函数的参数,成员函数本身,以及成员函数返回值得修饰

在class外
修饰常量问题不大,比如const int num=5;
修饰局部作用域的static变量比如
{
const static pi=3.1415926;
}
被修饰过的常量不可以再改变它的值

如果修饰指针
比如
char gr[]=”Hello,World!”;
const char* p=gr;
或者说const char* const p=gr;
可能有人比较乱
只需记住*左边const修饰指针指向的内容,表示指针指向的数据是常量
*右边的const修饰指针本身,即指针是常量,或者是指针所指向的地址无法改变,但是你可以改变指针指向的数据

比如
{
char gr[]=”Hello,World!”;
const char* p=gr;
p[0]=”w”;//错误,内容无法改变;
}
{
char gr[]=”Hello,World!”;
char* const p=gr;
p++;//错误,指针本身不可以被改变;
}

//亦如STL
std::vector<int> vec;
...
const std::vector<int>::iterator iter=vec.begin();
*iter=10;//正确
++iter;//错误,迭代器本身是常量

std::vector<int>::const_iterator cIter=vec.begin();
*cIter=10;//错误,cIter指向的内容是常量
++cIter;//没问题

修饰函数

const修饰函数参数,常用的是const指针或者const引用

对于class来说,const似乎更有用
1.修饰非static成员变量 记住这样的成员变量在初始化时不能赋值,只能使用构造函数的初始化列表
2.修饰static成员变量,这样的成员变量可以在声明时给它初始化(这里只是在声明),然后在类外进行定义(这里不能再次赋值)
class GamePlayer
{
private:
static const int Num=5;//声明

};
const int GamePlayer::Num;//定义

如果编译器不允许in class 初值设定
那么只能这么写
class GamePlayer
{
private:
static const int Num;//声明

};
const int GamePlayer::Num=5;//定义

如果必须要用到这个const static 变量,但是编译器不允许完成in class 初值设定,那么只能借助enum
class GamePlayer
{
private:
enum {Num=5};
int scores[Num];

};
有很长一段时间我不理解为什么static const不能使用初始化列表,然而我忽然想到了,static变量属于共享变量,不可能被某个单独的对象所拥有,所以只能采用如此独特的初始化方式
3.修饰成员函数,包括参数,函数本身,函数返回值
(1).比如有些函数,由于传入的是自定义结构体,为了效率,只能使用引用,我们不希望传入的参数发生改变,只能使用const
(2).比如如果我不希望改变任何成员变量,只能对成员函数本身使用const
(3).有些操作符的重载函数传回的值,我们不想它被改变,就需要对返回值作const修饰

#include <windows.h>
#include <iostream>
#include <string>
using namespace std;

class PT
{
    friend ostream& operator<<(ostream& out,PT& pt)
    {
        out<<pt.m_x<<" "<<pt.m_y;
        return out;
    }
    friend PT operator+(const PT& lhs,const PT& rhs)//const修饰返回值,防止返回的值被再次赋值(预防比如(a+b==c)误写成(a+b=c)这种情况)
    {
        PT pt;
        pt.m_x=lhs.m_x+rhs.m_x;
        pt.m_y=lhs.m_y+rhs.m_y;
        return pt;
    }
public:
    PT():m_x(0),m_y(0) {}
    ~PT(){}
    PT(int xPos,int yPos):m_x(xPos),m_y(yPos){}
    PT(const PT& pt):m_x(pt.m_x),m_y(pt.m_y){}
    const PT& operator=(const PT& other)//const修饰引用,既提高了效率,又防止乱修改
    {
        if(this==&other)
            return *this;
        this->m_x=other.m_x;
        this->m_y=other.m_y;
        return *this;
    }
    const int GetXPos() const {return this->m_x;}//const修饰函数,防止类的成员变量被改变
    const int GetYPos() const {return this->m_y;}

private:
    short m_x;
    short m_y;
};
int main()
{
    PT pt(12,33);
    cout<<pt<<endl;
    PT lhs(1,1);
    PT rhs(2,2);
    lhs+rhs=pt;//如果+重载函数的返回值没有const,这句话可以通过编译,加了const,则会弹出错误
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/baidu_25539425/article/details/79874896