• 『C++成长记』类和对象


     🔥博客主页:小王又困了

    📚系列专栏:C++

    🌟人之为学,不日近则日退 

    ❤️感谢大家点赞👍收藏⭐评论✍️


    目录

    一、类的引入

    二、类的定义

    三、类的访问限定符

    四、类的作用域

    五、类的实例化

    六、this指针

    📒6.1this指针的引出

    📒6.2 this指针的特性


    🗒️前言:

    🎀面向过程

         C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。用洗衣服举例。

    🎀面向对象

         C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。对于洗衣服这件事,C++设置了四个对象:人、衣服、洗衣粉、洗衣机。整个洗衣服的过程就变成了:人将衣服放进洗衣机、倒入洗衣粉、启动洗衣机,洗衣机就会完成洗衣过程并甩干。整个洗衣服的过程,是人、衣服、洗衣粉、洗衣机四个对象之间交互完成的,人不需要关心洗衣机具体是如何洗衣服的。

    一、类的引入

         C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现, 会发现struct中也可以定义函数。

    💌C语言版

    1. struct Stack
    2. {
    3. int* arr;
    4. int capacity;
    5. int size;
    6. };
    7. struct Stack s;//声明一个结构体变量
    8. void StackInit(struct Stack* ps);
    9. void StackPush(struct Stack* ps,int x);

         在C语言中,数据和方法分离,传递参数才能访问数据,没有对类型重定义只能写成struct Stack。函数名必须区分,要写成StackInit,在一个程序中如果有别的结构,例如:链表,就无法区分。

    💌C++版

    1. struct Stack
    2. {
    3. //函数
    4. void Init()
    5. {}
    6. void Push()
    7. {}
    8. //变量
    9. int* arr;
    10. int capacity;
    11. int size;
    12. };

         在C++中,类名就是类型,不需要加struct,而且不仅可以定义变量,还可以定义函数。变量可以通过.去调用类里面的函数。

    二、类的定义

    1. class className
    2. {
    3. //类体:由成员变量和成员函数组成
    4. };

         class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略

    类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。

    🎀类的两种定义方式:

    • 声明和定义全部放在类体中
    1. //定义一个人的类
    2. class Person
    3. {
    4. //成员函数——显式基本信息
    5. void showInfo()
    6. {
    7. cout << _name << "-" << _sex << "-" << _age << "-" << endl;
    8. }
    9. //成员变量
    10. char* _name;//姓名
    11. char* _sex;//性别
    12. int _age;//年龄
    13. };

    注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理,最终是否真的是内联,还是由编译器说了算。

    • 类声明放在.h文件中,成员函数定义放在.cpp文件中
    1. Person.h文件
    2. //定义一个人的类
    3. class Person
    4. {
    5. //成员函数——显式基本信息
    6. void showInfo();
    7. //成员变量
    8. char* _name;//姓名
    9. char* _sex;//性别
    10. int _age;//年龄
    11. };
    1. Person.cpp文件
    2. #include "Person.h"
    3. void Person::showInfo()
    4. {
    5. cout << _name << "-" << _sex << "-" << _age << "-" << endl;
    6. }

    注意:成员函数名前需要加类名: :,告诉编译器这个函数属于哪个类域。长的函数声明和定义分离,短的函数在类中定义。

    三、类的访问限定符

         C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。C++提供了三种限制权限的访问限定符:publicprotectedprivate

    🎀访问限定符说明

    • public修饰的成员在类外可以直接被访问(通过对象.访问)
    • protectedprivate修饰的成员在类外不能直接被访问(此处protected和private是类似的)
    • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 } 即类结束。
    • 如果后面没有访问限定符,作用域就到 } 即类结束。
    • class的默认访问权限为private,struct的默认访问权限为public(因为struct要兼容C)
    • 访问限定符可以修饰类中的成员变量、成员函数、内部类、重命名类型。友元函数的声明不受访问限定符的限制。

    注意:类定义数据一般是私有的 。

    四、类的作用域

         类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要::作用域限定符指明成员属于哪个类域。不同的类域里面可以定义同名变量。

    1. //定义一个人的类
    2. class Person
    3. {
    4. //成员函数
    5. void Person();
    6. //成员变量
    7. char* _name;//姓名
    8. char* _sex;//性别
    9. int _age;//年龄
    10. };
    11. // 这里需要指定PersonInfo是属于Person这个类域
    12. void Person::PersonInfo()
    13. {
    14. cout << _name << "-" << _sex << "-" << _age << "-" << endl;
    15. }

         如上面的成员函数PersonInfo,对于函数体中出现的变量_name等,编译器会先在当前函数的局部域中搜索,如果没有找到,接下来会到对应的类域里面去搜索,当类域里面也没有的时候,最后回到全局区搜索,如果全局也没有,编译就会报错。

    五、类的实例化

    用类型创建对象的过程,称为类的实例化。

         类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。类和对象的关系可以看成,拿图纸建房子的过程,图纸就是类,建出来的一栋栋房子,就是一个个的对象。

         一个类可以实例化出多个对象,就像一个图纸,可以建成很多房子一样,实例化出的对象占用实际的物理空间,存储类成员变量。

    1. class Person
    2. {
    3. //成员函数
    4. void Person::PersonInfo()
    5. //成员变量
    6. char* _name;//姓名
    7. char* _sex;//性别
    8. int _age;//年龄
    9. };
    10. int main()
    11. {
    12. Person p1;//用类实例化一个对象p1
    13. Person p2;//用类实例化一个对象p2
    14. p1._name = "张三";
    15. p1._sex = "男";
    16. p1._age = 19;
    17. return 0;
    18. }

    六、this指针

    📒6.1this指针的引出

         我们先观察下面的代码 

    1. class Date
    2. {
    3. public:
    4. void Init(int year, int month, int day)
    5. {
    6. _year = year;
    7. _month = month;
    8. _day = day;
    9. }
    10. void Print()
    11. {
    12. cout << _year << "-" << _month << "-" << _day << endl;
    13. }
    14. private:
    15. int _year; // 年
    16. int _month; // 月
    17. int _day; // 日
    18. };
    19. int main()
    20. {
    21. Date d1, d2;//定义两个日期类
    22. d1.Init(2022, 1, 11);//给d1初始化化
    23. d2.Init(2022, 1, 12);//给d2初始化
    24. d1.Print();//调用Print函数
    25. d2.Print();//调用Print函数
    26. return 0;
    27. }

    对于上述类,有这样的一个问题:

    Date类中有 Init Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

    C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏 的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编 译器自动完成。

    1. void Print()
    2. {
    3. cout << _year << "-" << _month << "-" << _day << endl;
    4. }
    5. void Print(Date* const this)
    6. {
    7. cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
    8. }

    📒6.2 this指针的特性

    1.  this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
    2.  只能在“成员函数”的内部使用.
    3.  this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。
    4.  this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递。

    本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

  • 相关阅读:
    笙默考试管理系统-MyExamTest----codemirror(16)
    Spring Security oauth2.0 客户端
    钡铼技术有限公司R40路由器工业4G让养殖环境监控更高效
    c语言上机作业:迭代法求平方根
    MASA Stack 第五期社区例会
    实验5 二叉树的应用程序设计
    修改http_charfinder.py使能在python311环境中运行
    第五章:Spring细分一如何让mapper文件夹下的SQL语句对数据库生效,jdbc和mybatis-config.xml
    多模态GPT-V出世!36种场景分析ChatGPT Vision能力,LMM将全面替代大语言模型? | 京东云技术团队
    react: zustand数据缓存
  • 原文地址:https://blog.csdn.net/2301_76207836/article/details/134077086