分享

【C++】类的默认成员函数----const成员函数(超详细解析)-CSDN博客

 补丁牛仔裤 2024-09-19 发布于广东

目录

一、前言

二、const成员函数 

🍎const修饰类的成员函数 

💦问题1 

💦问题2

💦针对const成员函数的常考面试题(重点!!)

🍐取地址及const取地址操作符重载

三、共勉


一、前言

   在我们前面学习的中,我们会定义成员变量成员函数,这些我们自己定义的函数都是普通的成员函数,但是如若我们定义的类里什么也没有呢?是真的里面啥也没吗?如下:

class Date {};

  如果一个中什么成员都没有,简称为空类。空类中什么都没有吗?并不是的任何一个类在我们不写的情况下,都会自动生成6个默认成员函数。


【默认成员函数概念】:用户没有显式实现,编译器会生成的成员函数称为默认成员函数


⭐其中上次的博客已经详细的讲解了构造函数&&析构函数的使用方法与拷贝构造函数和赋值运算符重载,所以本次博客将继续深度的讲解const成员函数问题

二、const成员函数 

🍎const修饰类的成员函数 

【概念】:将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针表明在该成员函数中不能对类的任何成员进行修改 

💦问题1 

 假如我现在有一个日期类,并且有如下的Func函数即调用情况:

  1. class Date
  2. {
  3. public:
  4. //构造函数
  5. Date(int year, int month, int day)
  6. {
  7. _year = year;
  8. _month = month;
  9. _day = day;
  10. }
  11. void Printf()
  12. {
  13. cout << _year << "年" << _month << "月" << _day << "日" << endl;
  14. }
  15. private:
  16. int _year;
  17. int _month;
  18. int _day;
  19. };
  20. void Func(const Date& d)
  21. {
  22. d.Printf();
  23. }
  24. int main()
  25. {
  26. Date d1(2023, 11, 1);
  27. d1.Printf();
  28. Date d2(2023, 11, 2);
  29. Func(d2);
  30. return 0;
  31. }

此时却出现了报错,这是为什么呢?

很明显,这里Func函数d的调用Print()出错了,而d1调用Print()却没出错,为何呢?

这里涉及到权限问题。我们先把实际调用过程中,隐含的this指针写出来:
如果对 this指针不了解的朋友可以看这篇博客:this 指针详解


Print()函数里的const修饰this本身,this不能修改,但是this可以初始化,接着我们要搞清楚&d1和&d的类型分别是啥:

  • &d1:Date*
  • &d:const Date*
  1. Date*传给Date* const没有问题,都是可读也可修改,所以d1调用Print()不会出错
  2. 而const Date* 指向的内容不能被修改,可是当它传给Date*时就出错了,因为Date*是可以修改的,这里传过去会导致权限放大。所以当然d调用Print()函数报错。



 

⭐解决办法: 
加上const去保护this指向的内容,也就是在Date*的前面加上const:

  1. void Print(const Date* const this)
  2. {
  3. cout << _year << "年" << _month << "月" << _day << "日" << endl;
  4. }

但是这里又不能之间加上const,因为this指针是隐含的,你不能显示的将const写出来。因此,C++为了解决此问题,允许在函数后面加上const以达到刚才的效果:
 

  1. void Print() const// 编译器默认处理成:void Print(const Date* const this)
  2. {
  3. cout << _year << "-" << _month << "-" << _day << endl;
  4. }

此时我const Date*传给const Date*就是权限不变,自然不会出错了,同样我Date*传给const Date*就是权限缩小也不会有问题。因为权限不能放大,只能缩小或不变。

正确的代码:

  1. class Date
  2. {
  3. public:
  4. //构造函数
  5. Date(int year, int month, int day)
  6. {
  7. _year = year;
  8. _month = month;
  9. _day = day;
  10. }
  11. void Printf() const // void Printf(Date* const this)
  12. {
  13. cout << _year << "年" << _month << "月" << _day << "日" << endl;
  14. }
  15. private:
  16. int _year;
  17. int _month;
  18. int _day;
  19. };
  20. void Func(const Date& d)
  21. {
  22. d.Printf(); // d.Printf(&d);
  23. }
  24. int main()
  25. {
  26. Date d1(2023, 11, 1);
  27. d1.Printf(); // d1.Printf(&d);
  28. Date d2(2023, 11, 2);
  29. cout << endl;
  30. Func(d2);
  31. return 0;
  32. }


 

 💦问题2

假如我们遇到如下,自定义类型的比较情况:

  1. class Date
  2. {
  3. public:
  4. //构造函数
  5. Date(int year, int month, int day)
  6. {
  7. _year = year;
  8. _month = month;
  9. _day = day;
  10. }
  11. bool operator<(const Date& d)
  12. {
  13. if (_year < d._year ||
  14. _year == d._year && _month < d._month ||
  15. _year == d._year && _month == d._month && _day < d._day)
  16. {
  17. return true;
  18. }
  19. else
  20. {
  21. return false;
  22. }
  23. }
  24. private:
  25. int _year;
  26. int _month;
  27. int _day;
  28. };
  29. int main()
  30. {
  31. Date d1(2023, 11, 1);
  32. const Date d2(2023, 11, 2);
  33. cout << endl;
  34. d1 < d2;
  35. d2 < d1;
  36. return 0;
  37. }

此时却出现了报错,这是为什么呢?

  • 首先对于第一个比较来说d1d2都是权限的保持
  • 接着对于第二个比较来说d1传递过去是权限的缩小,本来是可以修改了,现在不能修改;d2传递过去就变成了【权限的放大】,原本的d2const,但是this指针并没有加[const]做修饰,所以就造成了【权限方法】的问题

        那要怎么去做一个修改呢?此时就可以使用到我们上面所讲到的【const成员函数】,为当前的隐藏形参this 加上一个const做修饰,此时就可以做到【权限保持】

bool operator<(const Date& d) const

 💦针对const成员函数的常考面试题(重点!!)

问题1:const对象 可以调用 非const成员函数吗?


        这个当然不可以。我们前面已经说过了,若 const对象去调用非const成员函数,会造成【权限放大】的现象,原本在类外const对象的内容是不可以修改的,但是到了函数内部却有可以修改了,这是不被允许的

 问题2:非const对象 可以调用 const成员函数吗?


        这个当然是可以的。非const对象本身就是可读可写的,那在函数内部你要去修改或者不修改都不会有影响

 问题3:const成员函数内可以调用其它的非const成员函数吗?

       

       不可以,const成员函数内部只能调用const成员函数。因为const成员函数内部的this指针已经具有常属性的,万一这个非const成员函数去修改了成员变量的内容就会出问题了

 问题4:非const成员函数内可以调用其它的const成员函数吗?


       可以,权限缩小
 

🍐取地址及const取地址操作符重载

  1. class Date
  2. {
  3. public:
  4. //取地址&重载
  5. Date* operator&()
  6. {
  7. return this;
  8. }
  9. //const取地址&重载
  10. const Date* operator&()const
  11. {
  12. return this;
  13. }
  14. private:
  15. int _year;
  16. int _month;
  17. int _day;
  18. };

当然,如果我们自己不写&重载,编译器也会默认生成,可以通过打印来看看:

三、共勉

         以下就是我对【C++】类的默认成员函数----const成员函数的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对C++ 类和对象的理解,请持续关注我哦!!!  

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多