2.6、类中的常量(const)
2.6.1、const与函数
- 如果函数的参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。
- 如果输入参数以值传递的方式传递对象,则宜改用“const&”方式来传递,这样可以省去临时对象的构造和析构过程,从而提高效率。
- 在C++中,传递一个参数时,通常先选择通过引用传递,而且是通过常量(const)引用。
2.6.2、const修饰数据成员
-
const数据成员只在某个对象生存期内是常量,而对于整个类而言它则是一个变量。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。
-
const在每个对象中分配内存。
-
const修饰的数据成员生命周期是对象的生命周期,不同的对象其const数据成员的值可以不同。
-
不能在定义类的构造函数体内初始化const数据成员。const数据成员的初始化只能在类构造函数的初始化表中进行。
class Temp { public: Temp(int a, int b); private: const int m_a; //此时m_a是一个变量,会分配内存。 int m_b; }; Temp::Temp(int a, int b) : m_a(a) //再给构造函数分配空间前就已经给m_a赋值了。 { m_b = b; } int main() { Temp t(10, 20); return 0; } /* m_a 在Temp的生命周期里是一个变量, 但是在t的生命周期里是一个常量。 */
2.6.3、const修饰类成员函数
-
任何不修改成员数据的函数最好都声明成常成员函数。
-
用const修饰的函数,在声明和定义时都要加const。
-
构造函数和析构函数都不能为const(因为他们必然修改对象)。
class Person { public: void display() const; private: int m_id; int m_age; } void Person::display() const { cout << m_id << m_age << endl; }
2.6.4、const修饰类对象
-
const修饰类对象(方式与普通的数据类型定义一样:const Person t);
-
用const修饰的对象只能调用const成员函数。
-
例子
#include <iostream> using namespace std; class R { public: R(int r1,int r2); void print(); void print1() const; //常成员函数 private: int m_r1,m_r2; const int mc_d1,mc_d2; }; R::R(int r1,int r2):mc_d1(250),mc_d2(200) //const数据成员初始化只能在类构造函数的初始化列表中进行 { m_r1 = r1; m_r2 = r2; } //this指针是隐藏在每一个类的成员函数中的特殊指针 void R::print() //此时this指针是: R *this; { cout << m_r1 << ":" << m_r2 << endl; cout << mc_d1 << ":" << mc_d2 << endl; } void R::print1()const //常成员函数,此时this指针是:const R *this; { cout << m_r1 << ":" << m_r2 << endl; cout << mc_d1 << ":" <<mc_d2 << endl; } int main() { R a(5,4); a.print(); a.print1(); const R b(20,52); b.print1(); // b.print(); return 0; }
2.6.5、const的例外
1、要使某个成员变量在const对象中可以被修改、有两种方式:
- 把常函数中隐含的this指针强制转换为非const。
- 更为常用的规范做法是:把希望可被改变的数据成员声明为mutable。
2、mutable的用法
- const 所修饰的函数中,要由编译器负责保护类中的成员变量不被修改。
- mutable则是用来修饰类的成员变量,让该变量在const 所修饰的成员函数中可以被修改。
- 并且const 修饰的函数只能是类的成员函数,mutable修饰的变量只能是类的成员变量。
#include <iostream>
using namespace std;
class Y
{
private:
//int j;
mutable int j; //mutable修饰的,所以可以在const修饰的成员函数中被修改
static int i; //静态成员变量
public:
void f() const;
Y(int x);
void print()const ;
};
int Y::i = 5; //静态成员变量初始化
Y::Y(int x):j(x)
{
}
void Y::print() const
{
cout << "j = " << j << endl;
cout << "i = " << i << endl;
}
void Y::f()const
{
//((Y*)this)-> j = 100; //通过强制类型转换把本来是const Y *this的指针转化成Y *this。
this-> j = 100;
}
int main()
{
const Y y(10);
const Y y1(20);
y.print();
y.f();
y.print();
y1.print();
return 0;
}