常成员

类的常成员分为常数据成员和常成员函数。“常”代表“只读”,也就是说一旦确立,一般情况下不会被改变。

常数据成员

常数据成员是只读变量,只能读取,不能修改。对于每个对象,常数据成员都是不可变的,但不同对象的常数据成员可以不同。在对其进行初始化的时候,要用到构造函数的初始化列表,而不能像其他变量一样,直接在构造函数内初始化。初始化列表在构造函数的()和{}之间,格式为:变量名(值)

class Date{
private:
    const int c;
    int b;
public:
    Date():c(5){//将c赋值为5
        b=2;//普通变量的初始化
    }
    Date(int x):c(x){//用参数将c赋值为x
        b=x;
    }
};
int main()
{
    Date d1,d2(6);
    return 0;
}

可以发现,常数据成员的存在并没有影响对象的定义:

  • 用无参构造函数定义对象d1,d1中b=2,c=5;
  • 用有参构造函数定义d2,d2中b=c=6;

定义完成后,常成员c永远是这个值,不能再更改,而普通成员b可以随意更改。

若有多个常数据成员,在初始化的时候用,隔开:

class Date{
private:
    const int a,b,c;
public:
    Date():a(5),b(2),c(1){}
    Date(int x):a(x),b(2),c(x){}
};

可以看出,如果没有需要初始化的普通数据成员,也不能省略{}

注意:若一个变量同为“常数据成员”和“静态数据成员”,那么要按照静态数据成员的方式进行初始化:

class Date{
private:
    static const int a;//static在前
};
const int Date::a=0;

常成员指针/引用

对于常成员指针、常成员引用,“初始化列表”中的()可以替代=的所有作用:

class Date{
private:
    const int t,&m,*p;
public:
    Date():t(2),m(t),p(&t){}
    //如果是普通数据成员,相当于m=t,p=&t
    void print(){
        cout<<m<<" "<<*p;
    }
};
int main( )
{
    Date d;
    d.print();
    return 0;
}

输出:

2 2

常成员函数

一般情况下,常成员函数不能修改变量,只能读取变量。常成员函数只在声明/实现的时候添加const符号,而调用的时候不再需要添加const符号。const符号添加在()和{}之间。

class Date{
private:
    const int y,m;
public:
    Date():y(2020),m(2){}//初始化
    void print() const;//声明(外联函数)
};
void Date::print() const {//实现
    cout<<y<<" "<<m;
}
int main( )
{
    Date d;
    d.print();//调用时没有添加const符号
    return 0;
}

输出:

2020 2

ps.常成员函数也可以修改一种特殊类型的变量:mutable型(与const型相反)

常对象

常对象不能调用普通成员函数,只能调用常成员函数。不过普通数据成员和常数据成员都可以被调用。
常对象定义时,类名const位置随意。

class Date{
private:
    const int y;
public:
    Date():y(2020){}
    void print() const{
        cout<<y;
    }//常成员函数
};
int main( )
{
    const Date d1;
    //const在前/在后都行
    Date const d2;
    d2.print();//常对象只能调用常成员函数
    return 0;
}