在C++中,常量的定义使用const。由于常量的值在程序运行过程中不能被改变,因此,定义或说明常量时必须对其进行初始化。
常量包含内置类型常量、对象类型常量(常量对象)、引用类型常量(常量引用)、常量对象成员(包括常量成员函数和常量数据成员)和指针常量(常量指针)等。本节介绍常量对象、常量引用、常量成员。
常量对象
常量对象的特点是它的数据成员的值在对象的整个生存期内都不能被修改。
常量对象的定义格式如下:
类名 const 对象名 {初始化};
//或者
const 类名 对象名 {初始化};
class A
{
public:
A(int i):id(i) //构造函数
{ }
void set(int i)//修改id的值
{
id = i;
}
~A()
{ }
private:
int id; //编号
};
int main()
{
A const a{ 1 };
const A b{ 1 };//等同上一行的定义
//a.set(10);//错误a的值不能修改
//b.set(20);//错误b的值不能修改
return 0;
}
常量成员
类的常量成员包括常量成员函数和常量数据成员。
常量成员函数(使用的最多的情况)
量成员函数的定义要使用const关键字,其定义格式为:
返回值 函数名(参数列表)const;//这个const说明对象本身的数据不能被修改
说明:
(1)该对象的this指针是隐藏的,为了表示不能修改对象本身的数据,在参数列表后面加const
(2)const是函数类型的一部分,在实现部分也要带该关键字。
(3)const关键字可用于区分重载函数。
(4)常量成员函数不能修改类的数据成员的值,也不能调用该类中没有用 const 修饰的成员函数,只能调用常量成员函数。
(5)非常量对象可以调用常量函数。
class A
{
public:
A(int i) :id(i) //构造函数
{ }
void set(int i)//修改id的值
{
id = i;
cout << "修改后的值:";
show();
}
void show()const //输出函数,常量函数
{
cout << "id=" << id << endl;
//id = 0;//错误,不能修改本身的数据
//set(0);//错误,常量函数不能调用非常量函数
}
~A()
{ }
private:
int id; //编号
};
int main()
{
A a{ 1 }; //非const对象
const A b{ 2 }; //const对象
a.show(); //非常对象 调用常函数
b.show(); //常对象 调用常函数
a.set(10); //非常对象 调用非常函数
//b.set(20); //错误,b的值不能修改,常对象不能调用非常函数
return 0;
}
常对象只能调用常成员方法,不能调用普通成员方法,常成员方法内部可以调用其它常方法,但不能调用普通方法
●普通对象可以调用常成员方法,也可以调用普通成员方法,普通成员方法内部可以使用其它普通成员方法也可以调用常成员方法.
常量成员数据
类的数据成员也可以是常量。使用 const 关键字说明的数据成员为常量数据成员。
对常量数据成员的赋值只能在类中定义成员变量时进行或者在构造函数的初始化列表中进行,当两种方式都存在时以构造函数的初始化列表为准.
class A
{
private:
const int m_a;//常数据成员,这个数据被初始化后再不能被修改 .例如 身份证号
int m_b;
public:
A(int a, int b) :m_a(a), m_b(b)//构造函数
{
//m_a = a;//错误的
//m_b = b;//可以
}
void show()const
{
cout << m_a << "," << m_b << endl;
}
};
int main()
{
A a{20,30};
a.show();
return 0;
}
C++11提供了一种新的初始化方式:就是在定义成员变量的时候直接赋值.如下
class B
{
private:
const int m_a=10;//在这初始化,但构造函数初始化列表中没有再修改
int m_b = 20;
const double m_c = 12.5;//在这初始化,且在构造函数初始化列表中有再修改
public:
B(double c):m_c(c)//构造函数 ,对c进行初始化
{
//m_a = 10;//错误的
//m_b = 200;//可以
//m_c = 23.4;//错误的
}
void show()const
{
cout << m_a << "," << m_b << "," << m_c << endl;
}
};
int main()
{
B b{56.7};
b.show();
return 0;
}
更加推荐下面的写法(更直观)
class C //const 成员在定义时直接给值 ,普通成员变量在构造函数中给值
{
private:
const int m_a = 10;//在这初始化,但构造函数初始化列表中没有再修改
int m_b;
const double m_c = 12.5;//在这初始化,且在构造函数初始化列表中有再修改
public:
C(int b) :m_b(b)//构造函数 ,对c进行初始化
{
}
void show()const
{
cout << m_a << "," << m_b << "," << m_c << endl;
}
};
int main()
{
C c{ 20 };
c.show();
return 0;
}
常量引用
在声明引用时用 const 修饰,那么被声明的引用就是常量引用。不能通过该引用修改对象的值。常用于修饰形参。
常量引用的声明格式如下:
const 类型说明符 &引用名;
void Show(const int& x)
{
x++; //错误,常量引用作为形参,其值不能被改变
cout << x << endl;
}
int main()
{
int i = 12;
Show(i);
return 0;
}
下面的是常量引用的主要使用场景,用于修饰形参。
class A
{
public:
A(int a = 0, int b = 0) :m_a(a), m_b(b)
{}
A(const A& ca)//拷贝构造函数,不允许修改ca的内容
{
m_a = ca.m_a;
m_b = ca.m_b;
}
private:
int m_a;
int m_b;
};
int main()
{
A a{10,20};
A b{ a };
return 0;
}