• [C++黑马程序员笔记]P113-P117类和对象-对象特性(2)


    视频地址:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili

    目录

    P113类和对象-静态成员

    P114类和对象-对象特性-成员变量和成员函数分开存储

    P115类和对象-对象特性-this指针的用途

    P116类和对象-对象特性-空指针访问成员函数 

    P117类和对象-对象特性-const修饰成员函数


    P113类和对象-静态成员

    静态成员就是在成员变量和成员函数前加上static,称为静态成员。

    静态成员分为:

    • 静态成员变量:
    1. 所有对象共享同一份数据
    2. 在编译阶段分配内存
    3. 类内声明,类外初始化
    • 静态成员函数
    1. 所有对象共享同一个函数
    2. 静态成员函数只能访问静态成员变量

    静态成员变量示例:

    1. using namespace std;
    2. #include<iostream>
    3. #include<string>
    4. //静态成员变量
    5. class Person {
    6. public:
    7. //所有对象都共享同一份数据
    8. //编译阶段就分配内存
    9. //类内声明,类外初始化操作
    10. static int m_A;
    11. //静态成员变量也是有访问权限的
    12. private:
    13. static int m_B;
    14. };
    15. int Person::m_A = 100;
    16. int Person::m_B = 200;
    17. void test01() {
    18. Person p;
    19. cout << p.m_A << endl;
    20. Person p2;
    21. p2.m_A = 200;
    22. cout << p.m_A << endl;
    23. }
    24. void test02() {
    25. //静态成员变量 不属于某一个对象,所有对象共享同一份数据
    26. //因此静态成员变量有两种访问方式
    27. //1、通过对象进行访问
    28. Person p;
    29. cout << p.m_A << endl;
    30. //2、通过类名进行访问
    31. cout << Person::m_A << endl;//Person::m_A可读为Person作用域下的m_A
    32. //cout << Person::m_B << endl; 类外访问不到私有静态成员变量
    33. }
    34. int main()
    35. {
    36. //test01();
    37. test02();
    38. system("pause");
    39. return 0;
    40. }

    静态成员函数示例:

    1. using namespace std;
    2. #include<iostream>
    3. #include<string>
    4. //静态成员函数
    5. //程序共享同一个函数
    6. //静态成员函数只能访问静态成员变量
    7. class Person {
    8. public:
    9. //静态成员函数
    10. static void func() {
    11. m_A = 100;//静态成员函数可以访问静态成员变量
    12. //m_B = 200;//静态成员函数不可以访问非静态成员变量,无法区分到底是哪个对象的m_B;
    13. cout << "static void func调用" << endl;
    14. }
    15. //静态成员函数也是有访问权限的
    16. private:
    17. static void func2() {
    18. cout << "static void fun2()调用" << endl;
    19. }
    20. static int m_A;
    21. int m_B;
    22. };
    23. int Person::m_A = 0;
    24. //有两种访问方式
    25. void test01() {
    26. //1、通过对象进行访问
    27. Person p;
    28. p.func();
    29. //2、通过类名进行访问
    30. Person::func();
    31. //Person::func2();//类外访问不到私有的静态成员函数
    32. }
    33. int main()
    34. {
    35. test01();
    36. system("pause");
    37. return 0;
    38. }

    P114类和对象-对象特性-成员变量和成员函数分开存储

    在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上。

    1. using namespace std;
    2. #include<iostream>
    3. #include<string>
    4. //成员变量和成员函数分开存储
    5. class Person {
    6. int m_A;//非静态成员变量 属于类的对象上的
    7. static int m_B;//静态成员变量 不属于类的对象上的
    8. void func() { };//非静态成员函数 不属于类的对象上
    9. static void func2() { };//静态成员函数 不属于类的对象上
    10. };
    11. int Person::m_B=0;
    12. void test01() {
    13. Person p;
    14. //空对象(Person类中为空)占用的内存空间为:1
    15. //C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
    16. //每个空对象也应该有一个独一无二的内存地址
    17. cout << " size of p:" << sizeof(p) << endl;
    18. }
    19. void test02() {
    20. Person p;
    21. cout << " size of p:" << sizeof(p) << endl;
    22. }
    23. int main()
    24. {
    25. //test01();
    26. test02();
    27. system("pause");
    28. return 0;
    29. }

    结果:

    当Person类中为空时,sizeof(p)为1;

    当Person类中有int m_A; static int m_B;时,sizeof(p)为4;

    当Person类中有int m_A; static int m_B;void func() { };时,sizeof(p)为4;

    当Person类中有int m_A; static int m_B;void func() { };static void func2() { };时,sizeof(p)为4;

    ---->说明:只有非静态成员变量在类的对象上。

    P115类和对象-对象特性-this指针的用途

    在C++中成员变量和成员函数是分开存储的。每一个非静态成员函数只会诞生一份函数实例,也就是多个同类型的对象共用一块代码。那么问题是:这一块代码是如何区分哪个对象调用自己呢?

    C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象。this指针是隐含每一个非静态成员函数内的一种指针;this指针不需要定义,直接使用即可。

    this指针的用途:

    在形参和成员变量同名时,可以用this指针来区分;

    在类的非静态成员函数中返回对象本身,可使用return *this。

    1. using namespace std;
    2. #include<iostream>
    3. #include<string>
    4. //1 解决名称冲突问题
    5. //2 返回对象本身用this
    6. class Person {
    7. public:
    8. Person(int age) {
    9. this->age = age;
    10. }
    11. Person& PersonAddage(Person& p) {
    12. this->age += p.age;
    13. //this指向p2的指针,而*this指向的就是p2这个对象本体
    14. return *this;
    15. }
    16. int age;
    17. };
    18. void test01() {
    19. Person p(18);
    20. cout <<"p的年龄为:" << p.age << endl;
    21. }
    22. //2 返回对象本身用this
    23. void test02() {
    24. Person p1(10);
    25. Person p2(10);
    26. //链式编程思想
    27. p2.PersonAddage(p1).PersonAddage(p1);
    28. cout << "p2的年龄为:" << p2.age << endl;
    29. }
    30. int main()
    31. {
    32. test01();
    33. test02();
    34. system("pause");
    35. return 0;
    36. }

    运行后的结果为:

    P116类和对象-对象特性-空指针访问成员函数 

    C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针。

    如果用到this指针,需要加以判断保证代码的健壮性

    示例:

    1. using namespace std;
    2. #include<iostream>
    3. //空指针调用成员函数
    4. class Person {
    5. public:
    6. void showClassName()
    7. {
    8. cout << "this is Person class" << endl;
    9. }
    10. void showAge() {
    11. cout << "age = " << m_Age << endl;
    12. }
    13. int m_Age;
    14. };
    15. void test01() {
    16. Person* p = NULL;
    17. p->showClassName();
    18. p->showAge();
    19. }
    20. int main()
    21. {
    22. test01();
    23. system("pause");
    24. return 0;
    25. }

    运行后的结果为:

    视频课程中运行到showAge()时会异常, 因此将showAge函数修改为:

    1. void showAge() {
    2. //报错原因是因为传入的指针为NULL
    3. if (this == NULL) {
    4. return;
    5. }
    6. cout << "age = " << m_Age << endl;
    7. }

    P117类和对象-对象特性-const修饰成员函数

    常函数:

    • 成员函数后加const后我们称这个函数为常函数
    • 常函数内不可以修改成员属性
    • 成员属性声明时加关键字mutable后,在常函数中依然可以修改

    常对象:

    • 声明对象前加const称该对象为常对象
    • 常对象只能调用常函数

    示例:

    1. using namespace std;
    2. #include<iostream>
    3. //常函数
    4. class Person {
    5. public:
    6. //this指针的本质 是指针常量 指针的指向不可以修改
    7. //const Person *const this
    8. //在成员函数后加const,修饰的是this指向,让指针指向的值也不可以修改
    9. void showPerson() const
    10. {
    11. this->m_B = 100;
    12. //this->m_A = 100;
    13. //this = NULL; //this指针不可以修改指针的指向
    14. }
    15. int m_A;
    16. mutable int m_B;//特殊变量,即使在常函数中,也可以修改这个值,加关键字mutable
    17. };
    18. //常对象
    19. void test02() {
    20. const Person p;//在对象前加const,变为常对象
    21. //p.m_A = 100;
    22. p.m_B = 10;//m_B是特殊值,在常对象下也可以修改
    23. //常对象只能调用常函数
    24. p.showPerson();
    25. }
    26. void test01() {
    27. }
    28. int main()
    29. {
    30. test01();
    31. system("pause");
    32. return 0;
    33. }

  • 相关阅读:
    打码半年,开源一款自定义大屏设计软件!
    linux jar包class热部署 工具 arthas安装及使用
    多维时序 | MATLAB实现WOA-CNN-BiLSTM-Attention多变量时间序列预测(SE注意力机制)
    LiveGBS流媒体平台GB/T28181功能-报警预案配置告警触发报警时截图及录像摄像头通过GB28181上报报警
    0x02. Spring Boot 3 之SpringBoot 版本升级最佳实践指南
    golang记录一下Reflect包Type类型NumMethod的一个小问题
    10. 一文快速学懂常用工具——网络工具(上)
    ERC4907:租赁中介,让你的NFT租赁像租房一样简单
    WPF —— MVVM架构
    风控(策略)岗中的模型知识须知
  • 原文地址:https://blog.csdn.net/weixin_45922730/article/details/127745605