• C++学习笔记(十三)


    在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十三篇博客。

    本篇博客介绍了C++的类的成员特性和友元。

    本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。

    目录

    成员特性

    静态成员

    类的成员的存储

    this指针

    空指针访问成员函数

    const修饰成员函数

    友元

    全局函数做友元

    友元类

    成员函数作为友元


    成员特性

    静态成员

    在成员变量和成员函数前加关键字static,就成为静态成员。

    静态成员变量是所有对象共享同一份数据,在编译阶段分配内存,类内声明,类外初始化。

    静态成员函数是所有对象共享同一个函数,只能访问静态成员变量。

    静态成员变量和静态成员函数可以通过对象和类名进行访问,但是依然有权限,私有的不可在类外访问。

    1. #include
    2. using namespace std;
    3. class test {
    4. public:
    5. static int num;
    6. static void show() {
    7. cout << "This is a test" << endl;
    8. cout << "num = " << num << endl;
    9. }
    10. private:
    11. static int number;
    12. static void func() {
    13. cout << "This is a function" << endl;
    14. }
    15. };
    16. int test::num = 10;
    17. int main(void)
    18. {
    19. test::show();
    20. test testtemp;
    21. testtemp.num = 20;
    22. testtemp.show();
    23. return 0;
    24. }

    类test有public权限的,静态的int类型成员变量num,和show函数,show函数访问num。也有private权限的静态的成员变量number和成员函数func。在类外初始化num的值为10,此处加作用域表明属于test类。

    main函数首先直接用类名访问了test类的show函数,随后实例化了一个对象,再通过对象修改num值为20并访问show函数。

    程序的输出是:

    This is a test
    num = 10
    This is a test
    num = 20
     

    类的成员的存储

    在C++中,只有非静态的成员变量才属于类的对象,其余都不属于。如果一个类对象没有非静态成员变量,那么会被分配一字节空间。

    1. #include
    2. using namespace std;
    3. class test1 {
    4. };
    5. class test2 {
    6. int num;
    7. static int number;
    8. void show1(){}
    9. static void show2(){}
    10. };
    11. int main(void)
    12. {
    13. cout << sizeof(test1) << endl;
    14. cout << sizeof(test2) << endl;
    15. return 0;
    16. }

    程序创建了两个类,test1类完全为空,test2类有非静态int变量,静态的int变量,静态函数,非静态函数各一个。程序获得这两个类的大小。程序输出:

    1
    4
     

    this指针

    this指针指向被调用的成员函数所属对象。this指针隐含在每个非静态成员函数内,不需要定义,可以直接使用。

    this指针可以用来区别同名形参和成员变量。另外,在类的非静态成员变量函数中返回对象本身可以用return *this。

    1. #include
    2. using namespace std;
    3. class test {
    4. private:
    5. int num;
    6. public:
    7. int getnum() {
    8. return num;
    9. }
    10. void setnum(int num) {
    11. this->num = num;
    12. }
    13. };
    14. int main(void)
    15. {
    16. test temp;
    17. temp.setnum(10);
    18. cout << temp.getnum() << endl;
    19. return 0;
    20. }

    程序的test类创建了private权限的变量num,以及对应的get和set函数。在setnum函数中使用this指针区分同名形参和成员变量。程序的输出是:

    10

    1. #include
    2. using namespace std;
    3. class test{
    4. public:
    5. int age;
    6. test& addage(test &temp) {
    7. this->age += 1;
    8. return *this;
    9. }
    10. };
    11. int main(void)
    12. {
    13. test temp;
    14. test fixed;
    15. fixed.age = 1;
    16. temp.age = 95;
    17. temp.addage(fixed);
    18. temp.addage(fixed);
    19. temp.addage(fixed);
    20. temp.addage(fixed);
    21. temp.addage(fixed);
    22. cout << "The age is " << temp.age << endl;
    23. return 0;
    24. }

    程序创建了一个test类,有一个成员变量age,和一个成员函数addage。addage成员函数接受一个test类对象的引用,将本类的成员age+1,随后返回本类对象。

    程序的输出是:

    The age is 100
     

    空指针访问成员函数

    空指针也可以调用成员函数,但是要注意有没有用到this指针。如果空指针调用时遇到this指针,程序崩溃。

    1. #include
    2. using namespace std;
    3. class test {
    4. public:
    5. int age;
    6. void show1(void) {
    7. cout << "This is null" << endl;
    8. }
    9. void show2(void) {
    10. if (this == NULL) {
    11. return;
    12. }
    13. cout << "The age is " << age << endl;
    14. }
    15. };
    16. int main(void)
    17. {
    18. test* p = NULL;
    19. (*p).show1();
    20. (*p).show2();
    21. return 0;
    22. }

    test类有成员变量age,成员函数show1和show2。show1函数输出This is null。show2函数进行判断,如果是空指针就结束,否则输出age的值。

    main函数中创建了一个test类指针,并赋值为NULL。随后调用show1和show2函数。程序的输出是:

    This is null

    const修饰成员函数

    在成员函数后加const就称为常函数,常函数内不可以修改成员属性。然而,在成员属性声明时加关键字mutable后,就可以在常函数中修改。

    在声明对象前加const就称为常对象,常对象只能调用常函数。

    1. #include
    2. using namespace std;
    3. class test {
    4. public:
    5. int number = 10;
    6. mutable int num = 10;
    7. void show(void) const {
    8. num = 15;
    9. cout << number << endl;
    10. cout << num << endl;
    11. }
    12. };
    13. int main(void)
    14. {
    15. test temp;
    16. temp.show();
    17. return 0;
    18. }

    test类的变量num被mutable修饰,成员函数show是常函数,内部修改了num的值,并进行一些输出。main函数创建了一个test类对象并调用show成员函数。

    程序的输出是:

    10
    15

    1. #include
    2. using namespace std;
    3. class test {
    4. public:
    5. int number = 10;
    6. mutable int num = 10;
    7. void show1(void) const {
    8. cout << number << endl;
    9. cout << num << endl;
    10. }
    11. void show2(void) {
    12. number = 20;
    13. num = 25;
    14. cout << number << endl;
    15. cout << num << endl;
    16. }
    17. };
    18. int main(void)
    19. {
    20. const test temp;
    21. temp.num = 5;
    22. temp.show1();
    23. return 0;
    24. }

    test类的成员变量num被mutable修饰。成员函数show1是常函数,show2不是常函数。

    main函数创建了一个test类的常对象,调用了show1函数。

    程序的输出是:

    10
    5

    友元

    有时候,需要访问某个类的private权限成员,就需要用友元。友元的目的是让一个函数或类访问另一个类的private成员。友元的关键字是friend

    友元可以通过全局函数,类或成员函数实现。

    全局函数做友元

    全局函数作为友元,需要在类的最上面加入要作为友元的函数的声明,同时前面加friend。

    1. #include
    2. using namespace std;
    3. class test {
    4. friend void look(test* p);
    5. public:
    6. int number = 10;
    7. private:
    8. int num = 15;
    9. };
    10. void look(test* p);
    11. int main(void)
    12. {
    13. test temp;
    14. look(&temp);
    15. return 0;
    16. }
    17. void look(test* p)
    18. {
    19. cout << (*p).number << endl;
    20. cout << (*p).num << endl;
    21. }

    test类有一个public权限的变量number,一个private权限的变量num。同时第一行声明look函数是友元。look函数接受一个test类指针作为参数,随后访问number和num成员。main函数创建了一个test类对象,随后将其作为参数传递给look函数。

    程序的输出是:

    10

    15

    友元类

    需要在类的第一行用friend class 类名;声明后面的类是友元类。

    1. #include
    2. using namespace std;
    3. class test {
    4. friend class look;
    5. public:
    6. int number = 10;
    7. private:
    8. int num = 15;
    9. };
    10. class look {
    11. public:
    12. test *temp = new test();
    13. void show(void);
    14. ~look() {
    15. delete temp;
    16. }
    17. };
    18. void look::show(void)
    19. {
    20. cout << (*temp).number << endl;
    21. cout << (*temp).num << endl;
    22. }
    23. int main(void)
    24. {
    25. look tmp;
    26. tmp.show();
    27. return 0;
    28. }

    test类有public权限的变量number和private权限的变量num。同时声明look为友元类。look类有一个成员变量temp,是test类的指针,开辟在堆区。成员函数show函数(实现在类外)访问temp的两个成员变量。main函数创建了一个look类对象,并调用show函数。

    程序的输出是:

    10
    15

    成员函数作为友元

    要在类的第一行放上成员函数的声明(加上作用域表明属于哪个类),然后前面加friend。

    1. #include
    2. using namespace std;
    3. class test;
    4. class look {
    5. public:
    6. test* temp;
    7. look();
    8. void show1(void);
    9. void show2(void);
    10. ~look() {
    11. delete temp;
    12. }
    13. };
    14. class test {
    15. friend void look::show1(void);
    16. public:
    17. int number = 10;
    18. private:
    19. int num = 15;
    20. };
    21. look::look() {
    22. temp = new test;
    23. }
    24. void look::show1(void)
    25. {
    26. cout << (*temp).number << endl;
    27. cout << (*temp).num << endl;
    28. }
    29. void look::show2(void)
    30. {
    31. cout << (*temp).number << endl;
    32. }
    33. int main(void)
    34. {
    35. look tmp;
    36. tmp.show1();
    37. tmp.show2();
    38. return 0;
    39. }

    第三行的class test;表明程序有一个test类,但是其定义在别处。下面的look类有一个test类指针temp作为成员,析构函数将temp释放。其构造函数,show1函数和show2函数的实现在下面。下面test类有public类型成员变量number和private类型成员变量num。test类第一行表明look类的show1函数是友元。再下面具体实现look类的构造函数,以及show1和show2函数。

    main函数创建了一个look类对象,并调用show1和show2函数。

    程序的输出是:

    10
    15
    10
     

  • 相关阅读:
    使用Ansible Template模块进行配置文件管理
    【深度学习】NLP,Transformer讲解,代码实战
    是时候为Spring Boot 3.0做准备了
    为什么蛋白质如此重要?它可以帮助你自然地减肥!
    [Apache Kafka 3.2源码解析系列]-5- Kafka的发送器对象的初始化
    浅谈电弧光保护在10kV变电站高压室的应用方案
    Tomcat请求处理流程与源码浅析
    【量化交易笔记】12.海龟交易策略
    Linux嵌入式串口UART测试程序
    conse8安装svn
  • 原文地址:https://blog.csdn.net/m0_71007572/article/details/126310022