• C++学习笔记(二十一)


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

    本篇博客介绍了C++的类模板。

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

    目录

    类模板

    类模板语法

    类模板和函数模板的区别

    类模板中成员函数创建时机

    类模板对象做函数参数

    类模板与继承

    类模板成员函数类外实现

    类模板分文件编写

    类模板与友元


    类模板

    类模板语法

    类模板的作用是建立一个通用类,类中的成员和数据类型可以不具体制定,用一个虚拟的类型代表。类模板的语法是:

    template

    template声明创建模板,typename表明后面的符号是一种数据类型,可以用class代替。T是数据类型名,可以替换,通常为大写字母。

    1. #include
    2. #include
    3. using namespace std;
    4. template<class a,class b>
    5. class person
    6. {
    7. public:
    8. a name;
    9. b age;
    10. person(a name, b age) {
    11. this->name = name;
    12. this->age = age;
    13. }
    14. void show() {
    15. cout << "The name is " << name << endl;
    16. cout << "The age is " << age << endl;
    17. }
    18. };
    19. int main(void)
    20. {
    21. personint> p("Jimena", 36);
    22. p.show();
    23. return 0;
    24. }

    person类使用了类模板,成员变量name的类型为a,age的类型为b。成员函数show输出信息。main函数创建了一个person类对象,并指明类型分别为string和int,随后调用show函数。程序的输出是:

    The name is Jimena
    The age is 36

    类模板和函数模板的区别

    类模板没有自动类型推导的使用方式,必须显示类型指定类型。类模板在模板参数列表中可以有默认参数。

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename A,typename B = int>
    5. class person {
    6. public:
    7. A name;
    8. B age;
    9. person(A name, B age) {
    10. this->name = name;
    11. this->age = age;
    12. }
    13. void show() {
    14. cout << "The name is " << name << endl;
    15. cout << "The age is " << age << endl;
    16. }
    17. };
    18. int main(void)
    19. {
    20. personint> p1("Kate", 18);
    21. personp2("Kevin", 21);
    22. p1.show();
    23. p2.show();
    24. return 0;
    25. }

    程序的类模板默认B为int类型,因此在创建类的同时,尖括号内可以省略B的类型,此时B为int类型。程序的输出是:

    The name is Kate
    The age is 18
    The name is Kevin
    The age is 21
     

    类模板中成员函数创建时机

    普通类的成员函数一开始就可以创建,而类模板的成员函数在调用时才创建。

    类模板对象做函数参数

    类模板实例的对象,可以向函数传参。传入方式有这三种:

    指定传入的类型,这样直接显示对象的数据类型。

    参数模板化,这样将对象的参数变为模板进行传递。

    整个类模板化,这样将这个对象类型进行模板化再进行传递。

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename a,typename b>
    5. class person
    6. {
    7. public:
    8. a name;
    9. b age;
    10. person(a name, b age) {
    11. this->name = name;
    12. this->age = age;
    13. }
    14. void show(void) {
    15. cout << "The name is " << name << endl;
    16. cout << "The age is " << age << endl;
    17. }
    18. };
    19. void test(personint> &p)
    20. {
    21. p.show();
    22. }
    23. int main(void)
    24. {
    25. personint> p("Howard", 24);
    26. test(p);
    27. return 0;
    28. }

    程序用类模板创建了一个person类,在main函数中创建了一个对象p,并指明其成员类型。随后将p作为参数传递给test函数。test函数接受一个person类对象,同时在形参列表中指明了其成员类型。随后调用其show成员函数。

    程序的输出是:

    The name is Howard
    The age is 24

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename a, typename b>
    5. class person
    6. {
    7. public:
    8. a name;
    9. b age;
    10. person(a name, b age) {
    11. this->name = name;
    12. this->age = age;
    13. }
    14. void show(void) {
    15. cout << "The name is " << name << endl;
    16. cout << "The age is " << age << endl;
    17. }
    18. };
    19. template<typename a,typename b>
    20. void test(person& p)
    21. {
    22. p.show();
    23. }
    24. int main(void)
    25. {
    26. personint> p("Harvey", 17);
    27. test(p);
    28. return 0;
    29. }

    程序用类模板创建了一个person类,在main函数中创建了一个对象p,并指明其成员类型。随后将p作为参数传递给test函数。test函数使用了函数模板,将person类的两个成员变量类型指定为a和b,随后调用其show函数。

    程序的输出是:

    The name is Harvey
    The age is 17

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename a, typename b>
    5. class person
    6. {
    7. public:
    8. a name;
    9. b age;
    10. person(a name, b age) {
    11. this->name = name;
    12. this->age = age;
    13. }
    14. void show(void) {
    15. cout << "The name is " << name << endl;
    16. cout << "The age is " << age << endl;
    17. }
    18. };
    19. template<typename T>
    20. void test(T& p)
    21. {
    22. p.show();
    23. }
    24. int main(void)
    25. {
    26. personint> p("Hilary", 28);
    27. test(p);
    28. return 0;
    29. }

    程序用类模板创建了一个person类,在main函数中创建了一个对象p,并指明其成员类型。随后将p作为参数传递给test函数。test函数使用了类模板,将参数类型指定为T,随后调用其show函数。

    程序的输出是:

    The name is Hilary
    The age is 28

    类模板与继承

    如果子类继承的父类是一个类模板,那么子类在声明的时候要指定父类中T的类型,如果不指定就无法给子类分配内存。如果想灵活指定父类中T的类型,子类也要设置为类模板。

    1. #include
    2. using namespace std;
    3. template<typename T>
    4. class father
    5. {
    6. public:
    7. T fatherthing;
    8. void showfather(void) {
    9. cout << fatherthing << endl;
    10. }
    11. };
    12. class son :public father<int>
    13. {
    14. public:
    15. int sonthing;
    16. void showson(void) {
    17. cout << sonthing << endl;
    18. }
    19. };
    20. int main(void)
    21. {
    22. son s;
    23. s.sonthing = 10;
    24. s.fatherthing = 15;
    25. s.showson();
    26. s.showfather();
    27. return 0;
    28. }

    父类father使用了类模板,内含类型为T的成员变量fatherthing,和成员函数showfather,该成员函数输出fatherthing的值。子类son在继承父类时指明了T是int。son类本身有int类型成员变量sonthing,和成员函数showson,showson函数输出sonthing的值。

    main函数创建了一个son类型对象s,并进行了测试。程序的输出是:

    10
    15

    1. #include
    2. using namespace std;
    3. template<typename T>
    4. class father
    5. {
    6. public:
    7. T fatherthing;
    8. void showfather(void) {
    9. cout << fatherthing << endl;
    10. }
    11. };
    12. template<typename T>
    13. class son :public father
    14. {
    15. public:
    16. T sonthing;
    17. void showson(void) {
    18. cout << sonthing << endl;
    19. }
    20. };
    21. int main(void)
    22. {
    23. son<double> s;
    24. s.sonthing = 7.15;
    25. s.fatherthing = 11.40;
    26. s.showson();
    27. s.showfather();
    28. return 0;
    29. }

    父类father使用了类模板,内含类型为T的成员变量fatherthing,和成员函数showfather,该成员函数输出fatherthing的值。子类son也使用了类模板,son类本身有T类型成员变量sonthing,和成员函数showson,showson函数输出sonthing的值。

    main函数创建了一个son类型变量,并指定T为double类型。程序的输出是:

    7.15
    11.4

    类模板成员函数类外实现

    类模板成员函数在类外实现时,需要加上模板参数列表。

    1. #include
    2. using namespace std;
    3. template<typename T1,typename T2>
    4. class person
    5. {
    6. public:
    7. T1 name;
    8. T2 age;
    9. person(T1 name, T2 age);
    10. void show(void);
    11. };
    12. template<typename T1,typename T2>
    13. person::person(T1 name, T2 age) {
    14. this->name = name;
    15. this->age = age;
    16. }
    17. template<typename T1, typename T2>
    18. void person::show(void) {
    19. cout << "The name is " << name << endl;
    20. cout << "The age is " << age << endl;
    21. }
    22. int main(void)
    23. {
    24. personint> p("Ida", 13);
    25. p.show();
    26. return 0;
    27. }

    程序创建了类person,并将构造函数和成员函数show的实现放在了类外。这两个函数在实现时也加入了函数模板。main函数创建了一个对象,并进行了测试。程序的输出是:

    The name is Ida
    The age is 13
     

    类模板分文件编写

    类模板的成员函数在调用时创建,因此分文件编写时链接不到。

    可以通过直接包含.cpp源文件解决,但是一般不包含源文件。而是将声明和实现写在同一个文件中,将后缀改为.hpp。(.hpp是约定俗成的名称,非强制)

    1. #pragma once
    2. #include
    3. #include
    4. using namespace std;
    5. template<typename T1, typename T2>
    6. class person
    7. {
    8. public:
    9. T1 name;
    10. T2 age;
    11. person(T1 name, T2 age);
    12. void show(void);
    13. };
    1. #include
    2. #include
    3. #include"person.h"
    4. using namespace std;
    5. template<typename T1, typename T2>
    6. person::person(T1 name, T2 age) {
    7. this->name = name;
    8. this->age = age;
    9. }
    10. template<typename T1, typename T2>
    11. void person::show(void) {
    12. cout << "The name is " << name << endl;
    13. cout << "The age is " << age << endl;
    14. }

    这是person.h和person.cpp的内容,构成了person类的完整内容。person类使用了类模板。

    1. #include
    2. #include
    3. #include"person.cpp"
    4. using namespace std;
    5. int main(void)
    6. {
    7. personint> p("Ignacio", 37);
    8. p.show();
    9. return 0;
    10. }

    这是测试代码,直接包含了源文件。程序的输出是:

    The name is Ignacio
    The age is 37

    1. #pragma once
    2. #include
    3. #include
    4. using namespace std;
    5. template<typename T1, typename T2>
    6. class person
    7. {
    8. public:
    9. T1 name;
    10. T2 age;
    11. person(T1 name, T2 age);
    12. void show(void);
    13. };
    14. template<typename T1, typename T2>
    15. person::person(T1 name, T2 age) {
    16. this->name = name;
    17. this->age = age;
    18. }
    19. template<typename T1, typename T2>
    20. void person::show(void) {
    21. cout << "The name is " << name << endl;
    22. cout << "The age is " << age << endl;
    23. }

    person.hpp文件包含了person类的全部内容。person类使用了类模板。

    1. #include
    2. #include
    3. #include"person.hpp"
    4. using namespace std;
    5. int main(void)
    6. {
    7. personint> p("Ivan", 18);
    8. p.show();
    9. return 0;
    10. }

    这是测试代码,程序的输出是:

    The name is Ivan
    The age is 18

    类模板与友元

    全局函数实现友元可以在类内实现,也可以在类外实现。

    类内实现时直接在类内声明友元即可,类外实现时需要提前让编译器知道全局函数的存在。

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename A,typename B>
    5. class person
    6. {
    7. friend void show(person *p) {
    8. cout << "The name is " << p->name << endl;
    9. cout << "The age is " << p->age << endl;
    10. }
    11. public:
    12. person(A name,B age) {
    13. this->name = name;
    14. this->age = age;
    15. }
    16. private:
    17. A name;
    18. B age;
    19. };
    20. int main(void)
    21. {
    22. personint> p("Igor", 17);
    23. show(&p);
    24. return 0;
    25. }

    person类的友元函数show直接在person类内实现,前面加了friend表示是友元。main函数创建了一个person类对象,并使用show函数访问。程序的输出是:

    The name is Igor
    The age is 17
     

    1. #include
    2. #include
    3. using namespace std;
    4. template<typename A, typename B>
    5. class person;
    6. template<typename A, typename B>
    7. void show(person* p) {
    8. cout << "The name is " << p->name << endl;
    9. cout << "The age is " << p->age << endl;
    10. }
    11. template<typename A, typename B>
    12. class person
    13. {
    14. friend void show<>(person* p);
    15. public:
    16. person(A name, B age) {
    17. this->name = name;
    18. this->age = age;
    19. }
    20. private:
    21. A name;
    22. B age;
    23. };
    24. int main(void)
    25. {
    26. personint> p("Irma", 15);
    27. show(&p);
    28. return 0;
    29. }

    程序创建了person类,在person类内声明show函数是友元函数,声明时要加上空模板参数列表。程序的show函数在类外实现。main函数创建了一个person类对象,并调用show函数。

    程序的输出是:

    The name is Irma
    The age is 15

  • 相关阅读:
    Java————二叉树
    力扣206 - 反转链表【校招面试高频考题】
    echarts 学习网址
    Serverless 数仓技术与挑战 - 张雁飞|3306π
    Dynamics 365应用程序开发-2.使用应用程序模块设计器设计Apps
    maven
    Scala系列-2、scala函数式编程
    java.lang.UnsupportedOperationException 关于Arrays.asList问题解决
    手搭手zabbix5.0监控redis7
    英语教师杂志英语教师杂志社英语教师编辑部2022年第16期目录
  • 原文地址:https://blog.csdn.net/m0_71007572/article/details/126380130