• 【类和对象三部曲①】深入浅出类和对象


    1. 什么是对象?

    ​  对象是一个抽象概念,表示任意存在的事物。世间万物皆可为对象,现实世界中,随处可见的一个事物都是对象,对象是事物存在的实体,一个具体的人是对象,一本具体的书也可以是对象……


    2. 什么是类?

    ​  类是封装对象“属性”和“行为”的载体。反过来说,具有相同属性和行为的一类实体被称为类。举个例子:

    image-20220630171039391

    (图片来自网络)

    ​  类的范围可大可小,只要具有相同的属性和行为就可以归为一类。如果我们将类实例化,就可以得到一个具体的对象。

    image-20220630174317160

    3. 如何定义类?

    ​   类的定义有两种方式,早期使用struct来定义类,后来引入的关键字class来定义类,现在我们还是习惯于用class来定义类。

    ①用class定义类

    class className
    {
    	// 类体:由成员函数和成员变量组成
    };  // 一定要注意后面的分号
    
    • 1
    • 2
    • 3
    • 4

    ②用struct定义类:

    struct dog
    {
        //动作
        void eat() 
        {
            cout << "The dog is eating!" << endl;
        }
        //属性
        int _age;
        char _name[10];
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    C++中结构体被升级为类:

    • 结构体名称可以直接作为类型

      struct ListNode
      {
       	int val;
         	ListNode* next; // C++中不需要再加struct
      };
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • “结构体”中可以定义函数

    • 当然为了兼容C语言,C语言中关于结构体的操作都是相同的


    4. 封装

    ​   在C语言中,数据和方法是分离的。数据和方法分离的时候,虽然使用者自由度更高,但是对使用者的素养要求也更高。举个形象的例子:景区如果不设立围墙,不设置固定的出入口,那么人们就可以随意进出,随意破坏景点了;对应到我们的程序,就存在数据被篡改的风险。

    ​   我们可以看到,C++中的类将数据和方法放在一起,通过访问限定符来保护某些成员变量和成员函数,从而保证了类内部数据结构的完整性,防止外部操作对内部数据的干扰。


    5. 访问限定符

    ​ 访问限定符有三种,有以下几个注意点:

    • public 修饰的成员在类外可以直接被访问
    • protected 和 private 修饰的成员在类外不能直接被访问(在封装中protected 和 private 的功能是类似的 )
    • 一个类中可以有多个访问限定符,访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
    • class 的默认访问权限为 private,struct 为 public(因为struct要兼容C)
    class classname
    {
    public:
        // …… 成员函数访问权限通常为public
    
    private:
        // …… 成员变量的访问权限通常为private
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6. 类的定义域

    ​   由于类是一个整体,查找变量的时候会在整个类里面查找,所以成员函数可以定义在任何位置。


    7. 成员函数的定义

    成员函数的定义也有两种方式:

    ①在类里面定义

    class student
    {
    public:
        void init(int age, int score)
        {
            _age = age;
            _score = score;
        }
    
    private:
        int _age;
        int _score;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 在类里面定义的函数默认都是内联函数。这也给我们写代码指明了方向,在类里面定义的函数适合是短小的函数
    • 成员函数习惯前面加上“_”,否则 init 函数的参数名就比较别扭

    ②在类外面定义

    class student
    {
    public:
        void init(int age, int score);
    
    private:
        int _age;
        int _score;
    };
    
    void student::init(int age, int score)
    {
        _age = age;
        _score = score;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 在类里面放声明,定义放在类外面

    • 为了说明这个函数是类的成员函数,需要在函数名前加上类名和作用域分解运算符


    8. 实例化

    // 例如用上面的ListNode类来创建对象;
    int main()
    {
        ListNode node;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    反思:类中的成员变量占是定义还是声明?

    【答】定义还是声明取决是是否开辟空间。在创建类的时候并为成员变量开辟空间,所以只是声明,只有在实例化的时候才算是定义


    9. 对象的大小如何计算?

      对象中既有成员变量又有成员函数。对于成员变量而言,各个对象之间必然是相互独立且相互不同的,然而成员函数只需在固定的地方存储一份即可。具体存储模式如下图所示。在计算成员变量大小的时候仍然需要遵守内存对齐的规则。

    image-20220630225014352

     在反汇编下我们可以观察到,同一个类创建的多个对象在调用成员函数的时候,call指令所对应的函数地址都是相同的。


    10. this指针的介绍

    【问题】成员函数存储在公共代码区,所以函数体中没有关于不同对象的区分,那么函数是如何知道操作的是哪一个对象呢?

    【解决方法】C++引入关键字 this 指针。每个非静态成员函数都有一个隐藏参数 this 指针,在调用非静态成员函数的时候也会默认传入一个指针参数,该指针的作用是指向当前的对象。

    ​ 我们以下面的例子加以说明:

    class Date
    {
    public :
        void Display ()
        {
            cout <<_year<< "-" <<_month << "-"<< _day <<endl;
        }
        void SetDate(int year , int month , int day)
        {
            _year = year;
            _month = month;
            _day = day;
        }
    private :
        int _year ; // 年
        int _month ; // 月
        int _day ; // 日
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20220701185628979

    特性总结

    • ① this 指针的作用是保证每个对象拥有自己的数据成员,但共享处理这些数据的代码

    • ② 静态成员函数(函数名前加有static)为全体对象所共有,所以没有this指针

    • ③ this 指针是由编译器自动传递的,不能写在形参中,也不能在传参的时候不能手动传递。但this指针是可以使用的

      image-20220701190417342

      image-20220701190548589

      同时也可以证明 this 指针 指向当前对象

      image-20220701190742253
  • 相关阅读:
    YRX app第八题 python grpc
    [附源码]Python计算机毕业设计SSM健康饮食推荐系统(程序+LW)
    【Java面试】数据库连接池有什么用?它有哪些关键参数?
    Mysql不停机不锁表主从配置
    1.4_27 Axure RP 9 for mac 高保真原型图 - 案例26【中继器 - 后台管理系统4】功能-删除数据
    Java的数据类型
    全流程:安装uni-app(小程序端)
    如何开发自己的npm依赖包,开发-本地调试-打包发布到自己的镜像库
    C_C++在linux和windows下文件操作比较总结
    Could not create the Java virtual machine解决
  • 原文地址:https://blog.csdn.net/whc18858/article/details/125564483