[C++]const成员 - 详解
目录
观看建议:看这边文章前可以先复习该篇博客内容,可以更好理解本篇博客内容。[C语言]const 修饰 指针(看一遍就能懂)
1、为什么const成员变量必须在构造函数的初始化列表中初始化,而不能在构造函数体内赋值。
观看建议:看这边文章前可以先复习该篇博客内容,可以更好理解本篇博客内容。[C语言]const 修饰 指针(看一遍就能懂)
一、const成员变量
在 C++ 中,const 成员主要分为两类:const 成员变量和const 成员函数。它们共同保证了对象的某些部分在生命周期内不可被修改。
在类中声明的成员变量前面加上const关键字,表示这个成员变量是一个常量。
const成员变量必须在构造函数的初始化列表中进行初始化,因为一旦初始化后,其值就不能再改变。
注意:const成员变量不能使用赋值操作在构造函数体内初始化,必须使用初始化列表。
1、为什么const成员变量必须在构造函数的初始化列表中初始化,而不能在构造函数体内赋值。
const成员变量的常量特性:const成员变量一旦被初始化,其值就不能再改变。在对象的整个生命周期中,const成员变量只能被初始化一次。
构造函数体中的操作属于赋值,而不是初始化。当程序执行到构造函数体时,对象的所有成员已经经过了默认初始化(除非使用了初始化列表)。对于const成员变量,此时如果不在初始化列表中初始化,那么它就已经被默认初始化了(而且由于是const,之后不能再赋值),这会导致编译错误。
初始化列表是成员变量初始化的地方,特别是对于const成员、引用成员以及没有默认构造函数的类类型成员,都必须使用初始化列表进行初始化。
2 、const成员变量初始化时间线

3、const成员变量初始化编译器视角理解
// 伪代码:编译器视角的对象构造过程
void Test_constructor(Test* this, int a, int b) {
// 阶段1:成员初始化(初始化列表)
this->x = ???; // const成员必须在这里初始化
this->y = ???; // 非const成员也在这里初始化
// 阶段2:构造函数体执行
{
// 这里只能进行赋值操作
this->x = a; // 错误:const变量不能重新赋值
this->y = b; // 正确:非const变量可以赋值
}
}
二、const成员函数
在成员函数的参数列表后面加上const关键字,表示这个成员函数不会修改类的任何成员变量(除了被声明为mutable的成员变量)。
const成员函数可以被const对象调用,也可以被非const对象调用。但是非const成员函数只能被非const对象调用。
在const成员函数中,不能调用非const成员函数,因为非const成员函数可能会修改成员变量。
1、普通对象调用非const成员函数

class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
//非const成员函数
void Print()
{
cout << "void Print()" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//普通对象调用非const成员函数
Date d1(2025, 11, 23);
d1.Print();//权限平移 Date* const->Date* const
}
//输出结果
void Print()
year=2025 month=11 day=23
2、普通对象调用const成员函数

class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
//const成员函数
void Print() const
{
cout << "void Print() const" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//普通对象调用const成员函数
Date d1(2025, 11, 23);
d1.Print();//权限缩小 Date* const->const Date* const
}
//输出结果
void Print() const
year=2025 month=11 day=23
3、const对象不可以调用非const成员函数

class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
//非const成员函数
void Print()
{
cout << "void Print()" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//const对象不可以调用非const成员函数
const Date d2(2025, 11, 24);//const对象d2
d2.Print();//error this指针不可以权限放大 即 const Date* const->Date* const
}
4、const对象可以调用const成员函数

class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
//const成员函数
void Print() const
{
cout << "void Print() const" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//const对象可以调用const成员函数
const Date d3(2025, 11, 24);
d3.Print();//this指针权限平移 即 const Date* const->const Date* const
}
//输出结果
void Print() const
year=2025 month=11 day=24
5、const成员函数不能调用非const成员函数


class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)
{}
//非const成员函数
void noConstFunc()
{
cout << "void noConstFunc()" << endl;
}
//const成员函数
void ConstFunc() const
{
cout << "void ConstFunc() const" << endl;
}
void Print() const
{
cout << "void Print() const" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
//noConstFunc();//const成员函数不能调用非const成员函数
ConstFunc();//const成员函数可以调用const成员函数
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//const对象可以调用const成员函数
const Date d3(2025, 11, 24);
d3.Print();//this指针权限平移 即 const Date* const->const Date* const
}
//输出结果
void Print() const
year=2025 month=11 day=24
void ConstFunc() const
6、非const成员函数可以调用const成员函数

class Date
{
public:
//默认构造--全缺省构造
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)
{}
//非const成员函数
void noConstFunc()
{
cout << "void noConstFunc()" << endl;
}
//const成员函数
void ConstFunc() const
{
cout << "void ConstFunc() const" << endl;
}
//非const成员函数
void Print()
{
cout << "void Print()" << endl;
cout << "year=" << _year << " ";
cout << "month=" << _month << " ";
cout << "day=" << _day << endl;
ConstFunc();//非const成员函数可以调用const成员函数 涉及权限缩小
//即 Date* const->const Date* const
noConstFunc();//非const成员函数可以调用非const成员函数 涉及权限平移
//即 Date* const->Date* const
}
private:
int _year;
int _month;
int _day;
};
int main()
{
//普通对象调用非const成员函数
Date d1(2025, 11, 23);
d1.Print();
}
//输出结果
void Print()
year=2025 month=11 day=23
void ConstFunc() const
void noConstFunc()
三、总结
1、const成员变量
const成员变量必须在构造函数的初始化列表中进行初始化,因为一旦初始化后,其值就不能再改变。
2、const成员函数
对于const成员函数,对于是否可以调用只需要观察this指针权限的情况,权限平移和权限缩小都可以,但是权限放大不行。


浙公网安备 33010602011771号