• c++基础学习笔记——04-c++day08


    在学习c++基础总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    04-c++day08

    目录:
    一、C++模板
    1、函数模板基本使用
    2、课堂练习-实现通用的数组排序
    3、函数模板和普通函数区别
    4、函数模板和普通函数在一起调用规则
    5、模板机制
    6、函数模板的局限性
    7、类模板的基本使用
    8、成员函数创建时机
    9、类模板做函数的参数
    10、类模板碰到继承的问题以及解决
    11、类模板的类外实现成员函数
    12、类模板的分文件编写问题以及解决
    13、友元碰到类模板——友元函数类内实现
    14、友元碰到类模板——友元函数类外实现
    15、类模板的应用——数组类的封装
    二、总结

    一、C++模板


     c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就成为函数模板。凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现不同函数的功能。


    >c++提供两种模板机制:函数模板类模板
    >类属 - 类型参数化,又称参数模板


    总结:
    >模板把函数或类要处理的数据类型参数化,表现为参数的多态性,成为类属。
    >模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。


    1、函数模板基本使用

    用模板是为了实现泛型,可以减轻编程的工作量,增强函数的重用性。

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 
     5 //交换int类型两个数字
     6 void mySwapInt(int& a, int& b)
     7 {
     8     int temp = a;
     9     a = b;
    10     b = temp;
    11 }
    12 //交换double类型两个数字
    13 void mySwapDouble(double& a, double& b)
    14 {
    15     double temp = a;
    16     a = b;
    17     b = temp;
    18 }
    19 
    20 //类型、逻辑又非常相似
    21 //类型参数化,泛型编程——模板技术
    22 template<class T>//告诉编译器,下面如果出现T不要报错,T是一个通用的类型
    23 void mySwap(T& a, T& b)
    24 {
    25     T tmp = a;
    26     a = b;
    27     b = tmp;
    28 }
    29 
    30 //template<typename T> //等价于 template<class T>
    31 template<typename T>
    32 void mySwap2()
    33 {}
    34 
    35 
    36 void test01()
    37 {
    38     int a = 10;
    39     int b = 20;
    40     char c1 = 'c';
    41     
    42     //mySwapInt(a, b);
    43     //1.自动类型推导,必须有参数类型才可以推导
    44     mySwap(a, b);
    45     mySwap(a, c1);//推导不出来T,所以不能运行
    46     
    47     //2.显式指定类型
    48     mySwap<int>(a, b);
    49     
    50     //模板必须要指定出T才可以使用
    51     mySwap2<double>();//mySwap2();报错
    52     
    53     cout << "a = " << a << endl;
    54     cout << "b = " << b << endl;
    55     
    56     double a2 = 10;
    57     double b2 = 20;
    58     //mySwapInt(a2, b2);
    59     mySwap(a2, b2);
    60     
    61     
    62 }
    63 
    64 int main()
    65 {
    66     test01();
    67     
    68     system("pause");
    69     return EXIT_SUCCESS;
    70 }

    2、课堂练习-实现通用的数组排序

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 
     5 //对char和int数组进行排序,排序规则:从大到小,利用选择排序
     6 template<class T>
     7 void mySwap(T& a, T& b)
     8 {
     9     T tmp = a;
    10     a = b;
    11     b = tmp;
    12 }
    13 
    14 
    15 template<class T>
    16 void mySort(T arr[], int len)
    17 {
    18     for(int i = 0; i < len; i++)
    19     {
    20         int max = i;
    21         for(int j = i + 1; j < len; j++)
    22         {
    23             if(arr[max] < arr[j])
    24             {
    25                 //交换下标
    26                 max = j;
    27             }
    28         }
    29         if(max != i)
    30         {
    31             //交换数据
    32             mySwap(arr[max], arr[i]);
    33         }
    34         
    35     }
    36 }
    37 //输出数组元素的模板
    38 template<class T>
    39 void printArray(T arr[], int len)
    40 {
    41     for(int i = 0; i < len; i++)
    42     {
    43         cout << arr[i] << " ";
    44     }
    45     cout << endl;
    46 }
    47 
    48 void test01()
    49 {
    50     char charArr[] = "helloworld";
    51     int num = sizeof(charArr) / sizeof(char);
    52     mySort(charArr, num);
    53     printArray(charArr, num);
    54     
    55     int intArr[] = {1, 4, 100, 34, 55};
    56     int num2 = sizeof(intArr) / sizeof(int);//比较通用的方式求长度
    57     mySort(intArr, num2);
    58     printArray(intArr, num2);
    59 }
    60 
    61 int main()
    62 {
    63     test01();
    64     
    65     system("pause");
    66     return EXIT_SUCCESS;
    67 }

    3、函数模板和普通函数区别

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 
     5 //1.普通函数与函数模板区别
     6 template<class T>
     7 T myPlus(T a, T b)
     8 {
     9     return a + b;
    10 }
    11 
    12 int myPlus2(int a, int b)
    13 {
    14     return a + b;
    15 }
    16 
    17 
    18 void test01()
    19 {
    20     int a = 10;
    21     int b = 20;
    22     char c = 'c';
    23     
    24     myPlus(a, b);
    25     //myPlus(a, c);//类型推导不出来,函数模板不可以进行隐式类型转换
    26     myPlus2(a, b);
    27     cout << myPlus2(a, c) << endl;//10 + 99,普通函数,可以进行隐式类型转换
    28     
    29 }
    30 
    31 //2.普通函数和函数模板的调用规则
    32 template<class T>
    33 void myPrint(T a, T b)
    34 {
    35     cout << "模板调用的myPrint(a, b)" << endl;
    36 }
    37 
    38 template<class T>
    39 void myPrint(T a, T b, T c)
    40 {
    41     cout << "模板调用的myPrint(a, b, c)" << endl;
    42 }
    43 
    44 void myPrint(int a, int b)
    45 {
    46     cout << "普通函数调用的myPrint" << endl;
    47 }
    48 
    49 void test02()
    50 {
    51     int a = 10;
    52     int b = 20;
    53     
    54     //(1)如果出现重载,优先使用普通函数调用,如果没有实现,那就出现错误
    55     myPrint(a, b);
    56     
    57     //(2)如果想强制调用模板,那么可以使用空参数列表
    58     myPrint<>(a, b);
    59     
    60     //(3)函数模板可以发生重载
    61     int c = 30;
    62     myPrint(a, b, c);
    63     
    64     //(4)如果函数模板可以产生更好的匹配,那么优先调用函数模板
    65     char c2 = 'c';
    66     char d = 'd';
    67     
    68     myPrint(c2, d);
    69 }
    70 
    71 int main()
    72 {
    73     test01();
    74     
    75     system("pause");
    76     return EXIT_SUCCESS;
    77 }

     4、函数模板和普通函数在一起调用规则

     1)c++编译器优先考虑普通函数

     2)可以通过空模板实参列表的语法限定编译器只能通过模板匹配

     3)函数模板可以像普通函数那样可以被重载

     4)如果函数模板可以产生一个更好的匹配,那么选择模板

    5、模板机制

    思考:为什么函数模板可以和普通函数放在一起?c++编译器是如何实现函数模板机制的?

    hello.cpp程序是高级c语言程序,这种程序易于被人读懂。为了在系统上运行hello.c程序,每一条c语句都必须转化为低级的机器指令。然后将这些机器指令打包成可执行目标文件格式,并以二进制形式存储于磁盘中。
    预处理(Pre-processing) -> 编译(Compiling) ->汇编(Assembling) -> 链接(Linking)


    函数模板机制结论:

    1)编译器并不是把函数模板处理成能够处理任何类型的函数

    2)函数模板通过具体类型产生不同的函数

    3)编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。

    6、函数模板的局限性

    模板不能解决所有的类型,如果出现不能解决的类型,可以通过第三地具体化来解决问题。

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 class Person
     7 {
     8 public:
     9     Person(string name, int age)
    10     {
    11         this->m_Name = name;
    12         this->m_Age = age;
    13     }
    14     
    15     
    16     string m_Name;
    17     int m_Age;
    18 };
    19 
    20 template<class T>
    21 bool myCompare(T& a, T& b)
    22 {
    23     if(a == b)
    24     {
    25         return true;
    26     }
    27     return false;
    28 }
    29 
    30 //通过(第三代)具体化自定义数据类型,解决上述问题
    31 //如果具体化能够优先匹配,那么就选择具体化
    32 //语法:template<> 返回值 函数名<具体类型>(参数)
    33 template<> bool myCompare<Person>(Person& a, Person& b)
    34 {
    35     if(a.m_Age == b.m_Age)
    36     {
    37         return true;
    38     }
    39     return false;
    40 }
    41 
    42 void test01()
    43 {
    44     int a = 10;
    45     int b = 20;
    46     
    47     int ret = myCompare(a, b);
    48     
    49     cout << "ret = " << ret << endl;
    50     
    51     Person p1("Tom", 10);
    52     Person p2("Jerry", 10);
    53     
    54     int ret2 = myCompare(p1, p2);
    55     
    56     cout << "ret2 = " << ret << endl;
    57 }
    58 
    59 int main()
    60 {
    61     test01();
    62     
    63     system("pause");
    64     return EXIT_SUCCESS;
    65 }

    7、类模板的基本使用

    与函数模板区别,可以有默认类型参数; 函数模板可以进行自动类型推导,而类模板不可以

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 //类模板
     7 template<class NameType, class AgeType = int>//类模板可以有默认类型
     8 class Person
     9 {
    10 public:
    11     Person(NameType name, AgeType age)
    12     {
    13         this->m_Name = name;
    14         this->m_Age = age;
    15     }
    16     
    17     void showPerson()
    18     {
    19         cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    20     }
    21     
    22     NameType m_Name;
    23     AgeType m_Age;
    24 };
    25 
    26 void test01()
    27 {
    28     //自动类型推导,类模板,不支持
    29     //Person p("孙悟空", 100);
    30     
    31     //显示指定类型
    32     Person<string, int> p("孙悟空", 100);
    33     p.showPerson();
    34 }
    35 
    36 int main()
    37 {
    38     test01();
    39     
    40     system("pause");
    41     return EXIT_SUCCESS;
    42 }

    8、成员函数创建时机

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 //类模板
     7 template<class NameType, class AgeType>//类模板可以有默认类型
     8 class Person
     9 {
    10 public:
    11     Person(NameType name, AgeType age)
    12     {
    13         this->m_Name = name;
    14         this->m_Age = age;
    15     }
    16     
    17     void showPerson()
    18     {
    19         cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    20     }
    21     
    22     NameType m_Name;
    23     AgeType m_Age;
    24 };
    25 
    26 void test01()
    27 {
    28     //自动类型推导,类模板,不支持
    29     //Person p("孙悟空", 100);
    30     
    31     //显示指定类型
    32     Person<string, int> p("孙悟空", 100);
    33     p.showPerson();
    34 }
    35 
    36 class Person1
    37 {
    38 public:
    39     void showPerson1()
    40     {
    41         cout << "Person1的调用" << endl;
    42     }    
    43 };
    44 
    45 class Person2
    46 {
    47 public:
    48     void showPerson1()
    49     {
    50         cout << "Person2的调用" << endl;
    51     }    
    52 };
    53 
    54 template<class T>
    55 class myClass
    56 {
    57 public:
    58     T obj;
    59     void func1()
    60     {
    61         obj.showPerson1();
    62     }
    63     void func2()
    64     {
    65         obj.showPerson2();
    66     }
    67     
    68 };
    69 
    70 //成员函数一开始不会创建出来,而是在运行时才去创建
    71 
    72 void test02()
    73 {
    74     myClass<Person1> m;
    75     
    76     m.func1();
    77     
    78     //m.func2(;
    79 }
    80 
    81 
    82 int main()
    83 {
    84     test01();
    85     
    86     system("pause");
    87     return EXIT_SUCCESS;
    88 }

    9、类模板做函数的参数

    三种方式?

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 //类模板
     7 template<class NameType, class AgeType = int>//类模板可以有默认类型
     8 class Person
     9 {
    10 public:
    11     Person(NameType name, AgeType age)
    12     {
    13         this->m_Name = name;
    14         this->m_Age = age;
    15     }
    16     
    17     void showPerson()
    18     {
    19         cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    20     }
    21     
    22     NameType m_Name;
    23     AgeType m_Age;
    24 };
    25 
    26 //1.指定传入类型
    27 void doWork(Person<string, int>& p)
    28 {
    29     p.showPerson();
    30 }
    31 
    32 void test01()
    33 {
    34     Person<string, int> p("MT", 10);
    35     doWork(p);
    36 }
    37 
    38 //2.参数模板化
    39 template<class T1, class T2>
    40 void doWork2(Person<T1, T2>& p)
    41 {
    42     //如何查看类型?
    43     cout << typeid(T1).name() << endl;
    44     cout << typeid(T2).name() << endl;
    45     p.showPerson();
    46 }
    47 
    48 void test02()
    49 {
    50     Person<string, int> p("呆贼", 18);
    51     doWork2(p);
    52 }
    53 
    54 //3.整体模板化
    55 template<class T>
    56 void doWork3(T& p)
    57 {
    58     cout << typeid(T).name() << endl;
    59     p.showPerson();
    60 }
    61 
    62 void test03()
    63 {
    64     Person<string, int> p("劣人", 18);
    65     doWork3(p);
    66 }
    67 
    68 int main()
    69 {
    70     test01();
    71     
    72     system("pause");
    73     return EXIT_SUCCESS;
    74 }

    10、类模板碰到继承的问题以及解决

    基类如果是模板类,必须让子类告诉编译器 基类中的T到底是什么类型;如果不告诉,那么无法分配内存,编译不过。

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 using namespace std;
     4 
     5 template<class T>
     6 class Base
     7 {
     8 public:
     9     T m_A;//double类型
    10     
    11 };
    12 
    13 //child继承于base,必须告诉base中T的类型,否则T无法分配内存
    14 class Child:public Base<int>
    15 {
    16     
    17     
    18 };
    19 
    20 //child2也是模板类
    21 template<class T1, class T2>
    22 class Child2:public Base<T2>
    23 {
    24 public:
    25     Child2()
    26     {
    27         cout << typeid(T1).name() << endl;
    28         cout << typeid(T2).name() << endl;
    29     }
    30     
    31 public:
    32     T1 m_B;//int类型
    33 };
    34 
    35 void test01()
    36 {
    37     Child2<int, double>child;//由用户指定类型
    38     
    39 }
    40 
    41 int main()
    42 {
    43     test01();
    44     
    45     system("pause");
    46     return EXIT_SUCCESS;
    47 }

    11、类模板的类外实现成员函数

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 template<class T1, class T2>
     7 class Person
     8 {
     9 public:
    10     Person(T1 name, T2 age);
    11     /*{
    12         this->m_Name = name;
    13         this->m_Age = age;
    14     }
    15     */
    16     
    17     void showPerson();
    18     /*{
    19         cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    20     }
    21     */
    22     
    23     T1 m_Name;
    24     T2 m_Age;
    25 };
    26 
    27 //类外实现成员函数
    28 template<class T1, class T2>
    29 Person<T1, T2>::Person(T1 name, T2 age)
    30 {
    31     this->m_Name = name;
    32     this->m_Age = age;
    33 }
    34 
    35 template<class T1, class T2>
    36 void Person<T1, T2>::showPerson()
    37 {
    38     cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    39 }
    40 
    41 void test01()
    42 {
    43     Person<string, int>p1("Mt", 100);
    44     p1.showPerson();
    45 }
    46 
    47 int main()
    48 {
    49     test01();
    50     
    51     system("pause");
    52     return EXIT_SUCCESS;
    53 }

    12、类模板的分文件编写问题以及解决

    解决方案  保护 .cpp文件 (不推荐);不要进行分文件编写,写到同一个文件中,进行声明和实现,后缀名改为.hpp; 约定俗成的。

    类模板的分文件编写.cpp

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 #include"Person.hpp"
     6 
     7 //建议模板不要做分文件编写,写到一个类中即可,类内进行声明和实现,最后把后缀名改为.hpp(约定俗成)
     8 
     9 void test01()
    10 {
    11     Person<string, int>("猪八戒", 10);
    12     p.showPerson();
    13     
    14 }
    15 
    16 int main()
    17 {
    18     test01();
    19     
    20     system("pause");
    21     return EXIT_SUCCESS;
    22 }

    Person.hpp

     1 #pragma once
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 template<class T1, class T2>
     7 class Person
     8 {
     9 public:
    10     Person(T1 name, T2 age);
    11     
    12     void showPerson();
    13     
    14     T1 m_Name;
    15     T2 m_Age;
    16 };
    17 
    18 template<class T1, class T2>
    19 Person<T1, T2>::Person(T1 name, T2 age)
    20 {
    21     this->m_Name = name;
    22     this->m_Age = age;
    23 }
    24 
    25 template<class T1, class T2>
    26 void Person<T1, T2>::showPerson()
    27 {
    28     cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    29 }

    Person.h(不用)

     1 #pragma once
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 template<class T1, class T2>
     7 class Person
     8 {
     9 public:
    10     Person(T1 name, T2 age);
    11     
    12     void showPerson();
    13     
    14     T1 m_Name;
    15     T2 m_Age;
    16 };

    Person.cpp(不用)

     1 #include"Person.h"
     2 
     3 
     4 template<class T1, class T2>
     5 Person<T1, T2>::Person(T1 name, T2 age)
     6 {
     7     this->m_Name = name;
     8     this->m_Age = age;
     9 }
    10 
    11 template<class T1, class T2>
    12 void Person<T1, T2>::showPerson()
    13 {
    14     cout << "姓名:" << this->m_Name << "年龄:" << this->m_Age << endl;
    15 }

    13、友元碰到类模板——友元函数类内实现

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 template<class T1, class T2>
     7 class Person
     8 {
     9     //友元函数类内实现
    10     friend void printPerson(Person<T1, T2>& p)
    11     {
    12         cout << "姓名:" << p.m_Name << "年龄:" << p.m_Age << endl;
    13         
    14     }
    15     
    16     
    17 public:
    18     Person(T1 name, T2 age)
    19     {
    20         this->m_Name = name;
    21         this->m_Age = age;
    22     }
    23     
    24 private:
    25     T1 m_Name;
    26     T2 m_Age;
    27 };
    28 
    29 void test01()
    30 {
    31     Person<string, int> p("Tom", 10);
    32     printPerson(p);
    33 }
    34 
    35 int main()
    36 {
    37     test01();
    38     
    39     system("pause");
    40     return EXIT_SUCCESS;
    41 }

    14、友元碰到类模板——友元函数类外实现

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 
     6 //让编译器提前看到printPerson声明
     7 //让编译器看到Person类声明
     8 template<class T1, class T2>class Person;
     9 template<class T1, class T2>void printPerson(Person<T1, T2>& p);
    10 
    11 template<class T1, class T2>
    12 class Person
    13 {
    14     //友元函数类内实现,利用空参数列表<>,告诉编译器,模板函数的声明
    15     friend void printPerson<>(Person<T1, T2>& p);//普通函数的声明
    16     /*{
    17         cout << "姓名:" << p.m_Name << "年龄:" << p.m_Age << endl;
    18         
    19     }
    20     */
    21     
    22 public:
    23     Person(T1 name, T2 age)
    24     {
    25         this->m_Name = name;
    26         this->m_Age = age;
    27     }
    28     
    29 private:
    30     T1 m_Name;
    31     T2 m_Age;
    32 };
    33 
    34 //类外实现
    35 template<class T1, class T2>
    36 void printPerson(Person<T1, T2>& p)
    37 {
    38     cout << "姓名:" << p.m_Name << "年龄:" << p.m_Age << endl;
    39         
    40 }
    41 
    42 void test01()
    43 {
    44     Person<string, int> p("Tom", 10);
    45     printPerson(p);
    46 }
    47 
    48 int main()
    49 {
    50     test01();
    51     
    52     system("pause");
    53     return EXIT_SUCCESS;
    54 }

    15、类模板的应用——数组类的封装

    类模板的应用—数组类封装.cpp

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 #include"MyArray.hpp"
     6 
     7 //输出int类型数组
     8 void printIntArray(MyArray arr)
     9 {
    10     for(int i = 0; i < 10; i++)
    11     {
    12         cout << arr[i] << " " << endl;
    13     }
    14 }
    15 
    16 
    17 
    18 class Person
    19 {
    20 public:
    21     Person(){}
    22 
    23     Person(string name, int age)
    24     {
    25         this->m_Name = name;
    26         this->m_Age = age;
    27     }
    28     
    29     string m_Name;
    30     int m_Age;
    31     
    32 };
    33 
    34 //输出Person类型数组
    35 void printPersonArray(MyArray<Person>& array)
    36 {
    37     for(int i = 0; i < array.getSize(); i++)
    38     {
    39         cout << "姓名:" << array[i].m_Name << "年龄:" << array[i].m_Age << endl;
    40     }
    41 }
    42 
    43 int main()
    44 {
    45     MyArray<int>arr(10);
    46     for(int i = 0; i < 10; i++)
    47     {
    48         arr.push_Back(i + 100);
    49     }
    50     
    51     printIntArray(arr);
    52     
    53     Person p1("MT", 10);
    54     Person p2("呆贼", 12);
    55     Person p3("傻慢", 14);
    56     Person p4("劣人", 15);
    57     
    58     MyArray<Person>arr2(10);
    59     arr2.push_Back(p1);
    60     arr2.push_Back(p2);
    61     arr2.push_Back(p3);
    62     arr2.push_Back(p4);
    63     
    64     printPersonArray(arr2);
    65     
    66     system("pause");
    67     return EXIT_SUCCESS;
    68 }

    MyArray.hpp

     1 #pragma once
     2 #include<iostream>
     3 using namespace std;
     4 
     5 template<class T>
     6 class MyArray
     7 {
     8 public:
     9     //构造
    10     explicit MyArray(int capacity)//防止隐式类型转换,防止MyArray arr = 10;这样的写法,加上explicit
    11     {
    12         this->m_Capacity = capacity;
    13         this->m_Size = 0;
    14         this->pAddress = new T[this->m_Capacity];
    15     }
    16     
    17     MyArray(const MyArray& array)
    18     {
    19         this->m_Capacity = array.m_Capacity;
    20         this->m_Size = array.m_Size;
    21         this->pAddress = new T[this->m_Capacity];
    22         for(int i = 0; i < m_Size; i++)
    23         {
    24             this->pAddress[i] = array[i];
    25         }
    26     }
    27     
    28     ~MyArray()
    29     {
    30         if(this->pAddress != NULL)
    31         {
    32             delete[] this->pAddress;
    33             this->pAddress = NULL;
    34         }
    35         
    36     }
    37     
    38     //赋值操作符重载
    39     MyArray& operator=(MyArray& array)
    40     {
    41         //先判断原始数据,有就清空
    42         if(this->pAddress != NULL)
    43         {
    44             delete[] this->pAddress;
    45             this->pAddress = NULL;
    46         }
    47         
    48         this->m_Capacity = array.m_Capacity;
    49         this->m_Size = array.m_Size;
    50         this->pAddress = new T[this->m_Capacity];
    51         for(int i = 0; i < m_Size; i++)
    52         {
    53             this->pAddress[i] = array[i];
    54         }
    55     }
    56     
    57     //[]重载
    58     //MyArray arr(10)
    59     //arr[0] = 100;
    60     T& operator[](int index)
    61     {
    62         return this->pAddress[index];
    63     }
    64     
    65     //尾插法
    66     void push_Back(T val)
    67     {
    68         this->pAddress[this->m_Size] = val;
    69         this->m_Size++;
    70     }
    71     
    72     //获取大小
    73     int getSize()
    74     {
    75         return m_Size;
    76     }
    77     
    78     //获取容量
    79     int getCapacity()
    80     {
    81         return this->m_Capacity;
    82     }
    83     
    84 private:
    85     T* pAddress;//指向堆区指针
    86     int m_Capacity;//容量
    87     int m_Size;
    88 };

    二、总结

    1    函数模板基本使用
    1.1    template < class / typename  T> 告诉编译器紧跟的代码里出现T不要报错
    1.2    mySwap( T  &a  T  &b ) 类型也需要传入 ,类型参数化
    1.3    myswap(a,b) 自动类型推导  按照a b的类型 来替换T
    1.4    myswap<int>(a,b) 显示指定类型
    2    函数模板与普通函数的区别以及调用规则
    2.1    区别 普通函数可以进行隐式类型转换  模板不可以
    2.2    调用规则
    2.2.1    c++编译器优先考虑普通函数
    2.2.2    可以通过空模板实参列表的语法限定编译器只能通过模板匹配
    2.2.3    函数模板可以像普通函数那样可以被重载
    2.2.4    如果函数模板可以产生一个更好的匹配,那么选择模板
    2.3    模板的机制
    2.3.1    模板并不是万能的,不能通用所有的数据类型
    2.3.2    模板不能直接调用,生成后的模板函数才可以调用
    2.3.3    二次编译,第一次对模板进行编译,第二次对替换T类型后的代码进行二次编译
    3    模板局限性
    3.1    模板不能解决所有的类型
    3.2    如果出现不能解决的类型,可以通过第三地具体化来解决问题
    3.3    template<> 返回值 函数名<具体类型>(参数)
    4    类模板
    4.1    写法template <T…> 紧跟着是类
    4.2    与函数模板区别,可以有默认类型参数
    4.3    函数模板可以进行自动类型推导,而类模板不可以
    4.4    类模板中的成员函数 一开始不会创建出来,而是在运行时才去创建
    5    类模板做函数的参数
    5.1    三种方式
    5.1.1    显示指定类型
    5.1.2    参数模板化
    5.1.3    整体模板化
    5.2    查看类型名称
    5.2.1    cout << typeid(T).name() << endl;
    6    当类模板碰到继承
    6.1    基类如果是模板类,必须让子类告诉编译器 基类中的T到底是什么类型
    6.2    如果不告诉,那么无法分配内存,编译不过
    6.3    利用参数列表class Child :public Base<int>
    7    类模板的类外实现成员函数
    template <class T1, class T2>
    7.1    Person<T1, T2>::Person(T1 name, T2 age)
    8    类模板的分文件编写问题以及解决
    8.1    .h .cpp分别写声明和实现
    8.2    但是由于 类模板的成员函数运行阶段才去创建,导致包含.h头文件,不会创建函数的实现,无法解析外部命令
    8.3    解决方案  保护 .cpp文件 (不推荐)
    8.4    不要进行分文件编写,写到同一个文件中,进行声明和实现,后缀名改为.hpp
    8.5    约定俗成的
    9    类模板碰到友元函数
    9.1    友元函数类内实现
    9.2    friend void printPerson( Person<T1 ,T2> & p )
    9.3    友元函数类外实现
    9.4    friend void printPerson<>(Person<T1, T2> & p); //没有<>普通函数 声明  加上 <>模板函数声明
    9.5    让编译器看到 函数 并且看到这个Person类型
    10    类模板的应用——数组类的封装

    在学习c++基础总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    jquery 表单清空
    CK-Editor content.replace
    CSS DIV HOVER
    返回上一页并刷新与返回上一页不刷新代码
    Google Java编程风格指南中文版
    编程常见英语词汇
    教你如何删除tomcat服务器的stdout.log文件
    @Autowired @Resource @Qualifier的区别
    JSTL标签,EL表达式,OGNL表达式,struts2标签 汇总
    4.11 application未注入报错解决
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/CPlusPlus_BasicLearning_08.html
Copyright © 2020-2023  润新知