• C++初阶 | [二] 类和对象(上)


    摘要:class,成员函数,成员变量,类的大小,this 指针

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

    C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。


    1.  struct → class (类)

    Types

    • C语言:当我们用C语言创建一个自定义类型 (The Type is "struct MyBook") 来管理图书,首先在结构体中创建用于描述图书的有关参量,类似书名、价格、……,接着我们需要对此实现数据管理,因此我们需要实现一些函数来满足功能,类似打印图书信息之类的。如下代码。
      1. #include
      2. struct MyBook
      3. {
      4. char book_name[13];
      5. double price;
      6. };
      7. void Print(struct MyBook b_p)
      8. {
      9. printf("%s %f", b_p.book_name, b_p.price);
      10. }
      11. int main()
      12. {
      13. struct MyBook book = { "xxxx",13.7 };
      14. Print(book);
      15. return 0;
      16. }
    • C++:C++兼容C语言,仍然支持使用 struct 结构体,不仅如此,C++引入了 class 类。The Type is "MyBook_C" and "MyBook_CPP"。C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。另外,以C++方式实现, struct 中也可以定义函数。
      1. struct MyBook_C
      2. {
      3. void Print()
      4. {
      5. //……
      6. }
      7. char book_name[13];
      8. double price;
      9. };
      10. class MyBook_CPP
      11. {
      12. public:
      13. void Print()
      14. {
      15. ……
      16. }
      17. private:
      18. char* book_name;
      19. double price;
      20. };
      21. int main()
      22. {
      23. MyBook_C book1;
      24. MyBook_CPP book2;
      25. return 0;
      26. }

    访问限定符

    • public:公有,可以被访问的→ struct 默认
    • protected:受保护的
    • private:私有,不可被访问的 → class 默认

    class 中“类的成员”默认私有,在 class 类域外不可访问。

    访问限定符的作用域:从该访问限定符到下一个访问限定符或结束。

    (类内不受访问限定符的限制)

    注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别


    2. 类成员函数的声明和定义分离_member function

    类被定义之后会形成类域。函数声明与定义分离需要指明类域。在类内定义的函数默认是内联函数,代码量小、比较简单的函数一般直接在类中定义。


    3. 类成员变量的命名_Conventions

    1. class Date
    2. {
    3. public:
    4. void Init(int year = 0, int month = 0, int day = 0)
    5. {
    6. year = year;
    7. month = month;
    8. day = day;
    9. //局部变量优先,这里的操作是自己赋值给自己
    10. }
    11. private:
    12. int year;
    13. int month;
    14. int day;
    15. };

    所以,建议有所区分地命名: 例如

    1. class Date
    2. {
    3. public:
    4. void Init(int year = 0, int month = 0, int day = 0)
    5. {
    6. _year = year;
    7. _month = month;
    8. _day = day;
    9. }
    10. private:
    11. int _year;
    12. int _month;
    13. int _day;
    14. };

    4. sizeof(class)

    类的实例化→对象

    类对象的大小_空类

    class classname{ functions ; variables } 成员函数 functions 对于对象来说就像一个小区的公共区域,它们被存放在公共代码区(代码段);成员变量 variables 类实例化之后,要存储数据,对每一个实例化出来的对象都是私有的,并且这些变量遵循C语言的内存对齐规则,决定了 sizeof(classname) 的大小。如下图所示。

    C语言 结构体内存对齐规则:

    1. 第一个成员在与结构体偏移量为0的地址处。
    2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。 VS中默认的对齐数为8。
    3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
    4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

    • 总结:size of class 测试代码如下
    1. 类中由成员变量(和成员函数):遵循 C语言 内存对齐规则
    2. 类中只有成员函数:1 byte,表示占位,用于区分并表示实例化的对象
    3. 空类:1 byte,表示占位,用于区分并表示实例化的对象
      1. class Date
      2. {
      3. public:
      4. Date(const int year, const int month, const int day)
      5. {
      6. _year = year;
      7. _month = month;
      8. _day = day;
      9. }
      10. private:
      11. int _year;// 0 1 2 3
      12. int _month;// 4 5 6 7
      13. int _day;//8 9 10 11 → 12(内存对齐)
      14. };
      15. class Only_functions
      16. {
      17. public:
      18. void Print()
      19. {
      20. cout << "Only_functions" << endl;
      21. }
      22. };
      23. class Empty{};
      24. int main()
      25. {
      26. cout << sizeof(Date) << endl;//output:12
      27. cout << sizeof(Only_functions) << endl;//output:1
      28. cout << sizeof(Empty) << endl;//output:1
      29. Only_functions o1;
      30. o1.Print();
      31. cout << sizeof(o1) << endl;//output:1
      32. return 0;
      33. }


    5.this 指针

    1. warning:这里的隐藏的实参和隐藏的形参都不可以显式地写出 。👇 但是可以在类中显示地用:(如下代码,但一般不会像下面这样写,没什么意义)

      1. class Date
      2. {
      3. public:
      4. void Init(const int year = 2023, const int month = 1, const int day = 1)
      5. {
      6. this->_year = year;
      7. this->_month = month;
      8. this->_day = day;
      9. }
      10. private:
      11. int _year;
      12. int _month;
      13. int _day;
      14. };
    2. warningthis 指针是不可被修改的!(Type* const this = xxxxx),如果对 this 指针本身的内容进行修改会报错。

    指针问题

    1. nullptr -> member function  正常运行
    2. (*nullptr).member function  正常运行

    3. 真正发生了对空指针解引用的情况:


    END

  • 相关阅读:
    『LeetCode|每日一题』---->最小路径和
    Python入门系列(十)一篇学会python文件处理
    推荐系统之用户多兴趣建模(一)
    MySQL 数据库常用命令大全(完整版)
    SourceTree 的使用
    Spring控制事务
    DTDX991A 61430001-UW 自由IOT引入人工智能功能
    自动化运维工具Ansible教程(二)【进阶篇】
    阿里DataX极简教程
    (02)Cartographer源码无死角解析-(13) 开始轨迹→Node::AddTrajectory()
  • 原文地址:https://blog.csdn.net/fantastic_13_7/article/details/134184352