[C++]const成员

目录

[观看建议:看这边文章前可以先复习该篇博客内容,可以更好理解本篇博客内容。C语言const 修饰 指针(看一遍就能懂)](#观看建议:看这边文章前可以先复习该篇博客内容,可以更好理解本篇博客内容。[C语言]const 修饰 指针(看一遍就能懂))

一、const成员变量

1、为什么const成员变量必须在构造函数的初始化列表中初始化,而不能在构造函数体内赋值。

[2 、const成员变量初始化时间线](#2 、const成员变量初始化时间线)

3、const成员变量初始化编译器视角理解

二、const成员函数

1、普通对象调用非const成员函数

2、普通对象调用const成员函数

3、const对象不可以调用非const成员函数

4、const对象可以调用const成员函数

5、const成员函数不能调用非const成员函数

6、非const成员函数可以调用const成员函数

三、总结

1、const成员变量

2、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指针权限的情况,权限平移和权限缩小都可以,但是权限放大不行。

相关推荐
小poop3 小时前
CSS 基础与实战:从入门到精通网页美化
前端
会编程的小孩3 小时前
C++ qt的安装
c++
Csvn4 小时前
运行时性能
前端
Never_every995 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck5 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖6 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了7 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒7 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师8 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
特立独行的猫A8 小时前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos