• C++之类(持续更新)


    1、类的基础知识点

    1.1、类和对象

            和C中的结构体不同,在C++类中不仅可以定义变量,也可以定义函数。【在C++结构体中也可以定义变量和函数,但是一般情况下都使用类】。

            类的成员属性默认都是private;结构体的成员属性默认都是public。

    1. class student
    2. {
    3. public:
    4. // 共有成员(外部接口,可被使用该类的所有代码所使用的)
    5. student();
    6. ~student();
    7. void set_age(int age_t);
    8. private:
    9. // 私有成员(只允许本类中的函数访问,而类外部的任何函数都不允许访问)
    10. char name[50];
    11. int age;
    12. protected:
    13. // 保护成员(与private类似,差别表现在继承与派生时)
    14. };

            类中的元素称为类的成员;类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。

    1.2、类中成员函数定义

    (1)声明和定义都放在类体中

    1. // .h文件中
    2. class student
    3. {
    4. public:
    5. // 共有成员(外部接口,可被使用该类的所有代码所使用的)
    6. student();
    7. ~student();
    8. void set_age(int age_t)
    9. {
    10. age = age_t;
    11. }
    12. private:
    13. // 私有成员(只允许本类中的函数访问,而类外部的任何函数都不允许访问)
    14. char name[50];
    15. int age;
    16. protected:
    17. // 保护成员(与private类似,差别表现在继承与派生时)
    18. };

    (2)声明和定义分离

    1. // .h文件中
    2. class student
    3. {
    4. public:
    5. // 共有成员(外部接口,可被使用该类的所有代码所使用的)
    6. student();
    7. ~student();
    8. void set_age(int age_t);
    9. private:
    10. // 私有成员(只允许本类中的函数访问,而类外部的任何函数都不允许访问)
    11. char name[50];
    12. int age;
    13. protected:
    14. // 保护成员(与private类似,差别表现在继承与派生时)
    15. };
    1. // .cpp文件中
    2. void student::set_age(int age_t)
    3. {
    4. age = age_t;
    5. }

    1.3、类的作用域

            C++类重新定义了一个作用域,类的所有成员都在类的作用域中。在类外使用成员时,需要使用 ::(作用域解析符)来指明成员属于哪个类。

    1.4、实例化

            用类去创建对象的过程,称为类的实例化。类只声明了类有哪些成员,而并没有为成员分配内存空间。一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量

            类是对象的抽象和概括,而对象是类的具体和实例。

    1.5、类对象的存储方式

    C++程序占用的内存通常分为四个区:

            代码区(code area):存放着程序的二进制代码,由操作系统管理。

            全局区(static area):存放全局变量,静态变量,以及常量(字符常量和const修饰的全局变量)。

            栈区(stack area):存放所有的局部变量,其空间分配释放由编译器管理,当函数结束,局部变量自动被释放。

            堆区(heap area):存放所有动态开辟的变量,其空间分配释放由程序员管理。

    类对象存储如下:

    在类定义时:

            类的成员函数是被放在代码区。

            类的静态成员变量是存储在静态区的,即实例化的对象并不包括静态变量的创建。

            类的静态成员变量,在类的实例化过程中才在栈区或者堆区为其分配内存,是为每个对象生成一个拷贝,所以它是属于对象的。

    1. #include
    2. using namespace std;
    3. class student_1
    4. {
    5. public:
    6. void set_age(int age_t);
    7. private:
    8. char name[50];
    9. int age;
    10. static char aa[8];
    11. }std_1;
    12. class student_2
    13. {
    14. public:
    15. private:
    16. char name[50];
    17. int age;
    18. }std_2;
    19. class student_3
    20. {
    21. }std_3;
    22. int main(int argc, char argv[])
    23. {
    24. cout << " " << sizeof(std_1) << endl;
    25. cout << " " << sizeof(std_2) << endl;
    26. cout << " " << sizeof(std_3) << endl;
    27. return 0;
    28. }

    输出:

    1. 56
    2. 56
    3. 1

    结论:

            一个类的大小,实际就是该类中“成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。

    注意:

            这里的成员变量之和并不是简单的字节数相加,而是还要遵循内存对齐规则。

    1.6、this指针

    1. #include
    2. using namespace std;
    3. class student
    4. {
    5. public:
    6. void set_id(int grade_id__t, int class_id_t);
    7. void display_id_0()
    8. {
    9. cout << "grade_id: " << grade_id << ", class_id: " << class_id << endl;
    10. }
    11. void display_id_1()
    12. {
    13. cout << "grade_id: " << this->grade_id << ", class_id: " << this->class_id << endl;
    14. }
    15. private:
    16. char name[50];
    17. int age;
    18. int grade_id;
    19. int class_id;
    20. };
    21. void student::set_id(int grade_id__t, int class_id_t)
    22. {
    23. grade_id = grade_id__t;
    24. class_id = class_id_t;
    25. }
    26. int main(int argc, char argv[])
    27. {
    28. student std_1, std_2;
    29. std_1.set_id(10, 11);
    30. std_2.set_id(101, 34);
    31. std_1.display_id_0();
    32. std_1.display_id_1();
    33. std_2.display_id_0();
    34. std_2.display_id_1();
    35. return 0;
    36. }

    结果为:

    1. grade_id: 10, class_id: 11
    2. grade_id: 10, class_id: 11
    3. grade_id: 101, class_id: 34
    4. grade_id: 101, class_id: 34

    问题一:

            对于上述程序,std_1和std_2各自有不同的内存空间,而成员函数set_id中却并没有指定要对哪一个对象的成员进行操作,那么当std_1调用时函数是如何知道操作的对象是哪一个呢?

    答:

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

    this指针的特性:

            this指针的类型:类的类型* const,this在函数体内不可修改。

            只能在“成员函数”的内部使用。

            this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针。

            this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

    问题二:

            this指针的存储位置在哪里?

    答:

            临时变量都是存储在栈上的,因此this指针作为形参,存储在栈区。

    问题三:

            this指针可以为空指针吗?

    答:

            this指针可以为空指针,但切忌通过nullptr去访问指向的数据。

    1. #include
    2. using namespace std;
    3. class student
    4. {
    5. public:
    6. void set_id(int grade_id__t, int class_id_t);
    7. void display_id()
    8. {
    9. cout << "grade_id: " << grade_id << ", class_id: " << class_id << endl;
    10. }
    11. void display()
    12. {
    13. cout << "grade_id and class_id" << endl;
    14. }
    15. private:
    16. char name[50];
    17. int age;
    18. int grade_id;
    19. int class_id;
    20. };
    21. void student::set_id(int grade_id__t, int class_id_t)
    22. {
    23. grade_id = grade_id__t;
    24. class_id = class_id_t;
    25. }
    26. int main(int argc, char argv[])
    27. {
    28. student *std_1 = nullptr;
    29. std_1->display(); // 执行成功
    30. std_1->display_id(); // 执行失败
    31. return 0;
    32. }

            成员函数display()执行成功,而成员函数display_id()执行失败。首先nullptr地址我们是没有访问权限的,非法访问会使程序崩溃。

            display()执行成功,因为访问的是成员函数,成员函数不在对象内,就不会对指针解引用,std_1->的作用仅仅是指明了函数的类域,而函数内也没有使用到this指针,所以不会报错。

            display_id()执行失败,是因为在打印的时候调用了成员变量grade_id和class_id,而std_1又指向了nullptr,相当于访问了nullptr地址处的数据,因此程序崩溃。

    2、

    3、

    4、

    5、

    End、结语

    感谢参考的文档;参考的文档太多,不做一一列举。

    感谢大家提供的建议;

  • 相关阅读:
    SHA256 安全散列算法加速器实验
    计算机网络
    【Flink】FlinkCDC获取mysql数据时间类型差8小时时区解决方案
    三废的日常——什么是负载均衡
    5G 时代音视频开发前景怎么样?音视频开发需要掌握哪些技术?
    HR这个职位会消失?你怎么看?
    Tomcat 源码分析 (Tomcat的Session管理) (十一)
    Ajax——Ajax基础概念以及两种请求方式
    初尝pinia,相比于vuex轻量、好用
    C语言停车场管理系统
  • 原文地址:https://blog.csdn.net/qq_34486832/article/details/136767071