C++学习笔记23:const 成员函数

目录

[一、为什么需要 const 成员函数?](#一、为什么需要 const 成员函数?)

[二、const 成员函数的写法](#二、const 成员函数的写法)

[三、const 修饰的到底是什么?](#三、const 修饰的到底是什么?)

[四、const 成员函数不能修改成员变量](#四、const 成员函数不能修改成员变量)

[五、const 对象和普通对象的调用规则](#五、const 对象和普通对象的调用规则)

[1. const 对象只能调用 const 成员函数](#1. const 对象只能调用 const 成员函数)

[2. 普通对象可以调用 const 成员函数](#2. 普通对象可以调用 const 成员函数)

[3. 普通对象也可以调用普通成员函数](#3. 普通对象也可以调用普通成员函数)

六、成员函数之间的调用规则

[1. 普通成员函数可以调用 const 成员函数。](#1. 普通成员函数可以调用 const 成员函数。)

[2. const 成员函数不能调用普通成员函数](#2. const 成员函数不能调用普通成员函数)

七、在日期类中的应用

[八、构造函数和析构函数能不能加 const?](#八、构造函数和析构函数能不能加 const?)

[九、const 成员函数和 const 引用参数的关系](#九、const 成员函数和 const 引用参数的关系)

十、小结


一、为什么需要 const 成员函数?

在C++中,如果一个对象被 const 修饰,那么这个对象就不能被修改。

例如:

cpp 复制代码
const Date d(2024, 5, 1);

这里 d 是一个 const 对象,表示它的内容不能被修改。

如果我们写一个普通成员函数:

cpp 复制代码
void Print() {
    cout << _year << "-" << _month << "-" << _day << endl;
}

然后让 const 对象调用它:

cpp 复制代码
const Date d(2024, 5, 1);
d.Print();

这时可能会编译错误。

原因是:普通成员函数没有承诺不修改对象,而 const 对象不允许被修改。

所以 C++ 提供了 const 成员函数


二、const 成员函数的写法

const 成员函数就是在成员函数参数列表后面加上 const。

例如:

cpp 复制代码
void Print() const {
	cout << _year << "-" << _month << "-" << _day << endl;
}

完成示例:

cpp 复制代码
#include <iostream>
using namespace std;

class Date {
	public:
		Date(int year = 2024, int month = 1, int day = 1) {
			_year = year;
			_month = month;
			_day = day;
		}
		
		void Print() const {
			cout << _year << "-" << _month << "-" << _day << endl;
		}
	
	private:
		int _year;
		int _month;
		int _day;
};

int main() {
	const Date d(2024, 5, 1);
	d.Print();
	
	return 0;
}

运行结果:

cpp 复制代码
2024-5-1

加上 const 后,const 对象就可以正常调用 Print() 了。


三、const 修饰的到底是什么?

成员函数后面的 const,本质上修饰的是隐藏的 this 指针指向的对象。

普通成员函数中,this 指针可以理解为:

cpp 复制代码
Date* const this

也就是:

cpp 复制代码
this 指针本身不能改变指向的
但 this 指向的对象可以被修改

而 const 成员函数中,this 指针可以理解为:

cpp 复制代码
const Date* const this

也就是说:

cpp 复制代码
this 指针本身不能改变;
this 指向的对象也不能被修改。

所以在 const 函数中,不能修改成员变量。


四、const 成员函数不能修改成员变量

例如:

cpp 复制代码
void Print() const {
    _year = 2025;	// 错误 
	cout << _year << "-" << _month << "-" << _day << endl;
}

这段代码会报错。

原因是 Print() 被声明成了 const 成员函数,函数内部不能修改点给钱对象的成员变量。

所以 const 成员函数适用于:

cpp 复制代码
只读取对象数据,不修改对象状态的函数

比如:

cpp 复制代码
void Print() const;
bool operator==(const Date& d) const;
bool operator<(const Date& d) const;
int GetMonthDay(int year, int month) const;

五、const 对象和普通对象的调用规则

成员函数调用时,有一套权限规则。

1. const 对象只能调用 const 成员函数

cpp 复制代码
const Date d(2024, 5, 1);
d.Print();

如果 Print() 是普通成员函数,就可能报错。

应该写成:

cpp 复制代码
void Print() const {
	cout << _year << "-" << _month << "-" << _day << endl;
}

2. 普通对象可以调用 const 成员函数

cpp 复制代码
Date d(2024, 5, 1);
d.Print();

如果 Print() 是 const 成员函数,普通对象也可以调用。

因为普通对象权限更大,调用只读函数属于权限缩小,是安全的。


3. 普通对象也可以调用普通成员函数

cpp 复制代码
Date d(2024, 5, 1);
d.Print();

普通对象本来就可以修改,所以可以调用普通成员函数。


简单总结:

对象类型 普通成员函数 const成员函数
普通对象 可以调用 可以调用
const对象 不能调用 可以调用

六、成员函数之间的调用规则

成员函数内部也会涉及到 const 权限问题。

1. 普通成员函数可以调用 const 成员函数。

cpp 复制代码
class Date {
	public:
		void Func1() {
			Func2();
		}
		
		void Func2() const {
			cout << "Func2" << endl;
		}
};

这是可以的。

因为普通成员函数中的 this 是 Date*,调用 const 成员函数时,可以转换换成 const Date*,属于权限缩小。


2. const 成员函数不能调用普通成员函数

cpp 复制代码
class Date {
	public:
		void Func1 const () {
			Func2();    // 错误
		}
		
		void Func2() {
			cout << "Func2" << endl;
		}
};

这是错误的。

因为 const 成员函数中的 this 是 const Date*,如果调用普通成员函数,就相当于把 const Date* 转成 Date*,属于权限放大,不允许。


七、在日期类中的应用

之前写日期类比较运算符时,可写成这样:

cpp 复制代码
bool operator==(const Date& d) {
    return _year == d._year
        && _month == d._month
        && _day == d._day;
}

这个函数知识比较日期,不会修改当前对象。

所以更规范的写法应该是:

cpp 复制代码
bool operator==(const Date& d) const {
    return _year == d._year
        && _month == d._month
        && _day == d._day;
}

同理,下面这些比较函数也应该加 const:

cpp 复制代码
bool operator>(const Date& d) const;
bool operator<(const Date& d) const;
bool operator>=(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator!=(const Date& d) const;

这样 const Date 对象也可以正常调用这些函数。

哪些成员函数应该加 const?判断标准很简单:

只要这个成员函数不修改成员变量,就应该加 const。

不能加 const 的函数一般是会修改对象的,比如:

cpp 复制代码
Date& operator+=(int day);
Date& operator-=(int day);
Date& operator++();
Date& operator--();

八、构造函数和析构函数能不能加 const?

构造函数和析构函数不能写成 const 成员函数?

例如下面这种写法是错误的:

cpp 复制代码
Date() const {

}

~Date() const {

}

原因是构造函数和析

构函数本身负责对象的初始化和清理,不属于普通成员函数调用的场景。

所以:

cpp 复制代码
构造函数不能加 const
析构函数不能加 const

九、const 成员函数和 const 引用参数的关系

实际写代码时,函数经常会此写成:

cpp 复制代码
void Func() (const Date& d) {
	d.Print();
} 

这里 d 是 const Date&,也就是一个只读对象。

如果 Print() 没有加 const:

cpp 复制代码
void Print() {

}

那么:

cpp 复制代码
d.Print();

就会报错。

所以如果一个对象可以 const 引用形式传参,那么它调用的成员函数也应该是 const 成员函数。

这也是为什么在日期类中,Print()、比较运算符等不修改对象的函数 ,都应该加上const。


十、小结

本篇主要学习了C++中的 const 成员函数。

需要记住:

  1. const 成员函数是成员函数参数列表后面加 const;
  2. const 成员函数的本质是限制 this指针指向的对象不能修改;
  3. 普通对象可以调用普通成员函数和const 成员函数;
  4. const 对象只能调用 const 成员函数;
  5. const 成员函数内部不能修改成员变量;
  6. 普通成员函数可以调用 const 成员函数;
  7. const 成员函数不能调用普通成员函数;
  8. 不修改成员变量的函数都建议加 const;
  9. 构造函数和析构函数都不能加 const;
  10. 日期类中的比较函数、打印函数通常都应该写成 const 成员函数。

const 成员函数是写规范C++类代码时非常重要的知识点。理解它之后,就能很好的处理 const 对象、const 引用参数以及成员函数之间的调用权限问题。

相关推荐
3DVisionary2 小时前
精密模具电极如何测形变?蓝光三维扫描3D检测方案解析
c++·数码相机·蓝光三维扫描·质量控制 qc·形位公差分析·模具电极检测·非接触三维测量
小小编程路2 小时前
C++类作用域
java·jvm·c++
计算机安禾3 小时前
【c++面向对象编程】第46篇:CRTP(奇异递归模板模式):静态多态的妙用
开发语言·c++·算法
hhcgchpspk3 小时前
easyx按键游戏
c++·stm32·单片机·游戏·easyx
郝学胜-神的一滴3 小时前
Qt 高级开发 011: 跨线程信号槽实战
开发语言·c++·qt·程序人生·开源软件·用户界面
学困昇3 小时前
Linux 动静态库制作与原理:从 .a、.so 到 ELF 加载一次讲透
linux·运维·服务器·c语言·开发语言·c++·人工智能
basketball6163 小时前
C++面试考点 头文件与实现文件形式
开发语言·c++
历程里程碑3 小时前
56 . 高效ET非阻塞IO服务器设计指南
java·运维·服务器·开发语言·数据结构·c++·排序算法
计算机安禾4 小时前
【c++面向对象编程】第44篇:typename与class的区别,依赖类型名与template消除歧义
java·jvm·c++