栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

cpp-基本语法学习-Template

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

cpp-基本语法学习-Template

cpp提供两种模板机制 函数模板和类模板

函数模板 基本语法

建立一个通用的函数,返回值类型和形参类型不具体制定,用虚拟类型来代表
语法:

template

typename:表明后面符号是一种数据类型
T:通用数据类型,可替换
例:不同类型的相加

#include
using namespace std;
template//告诉编译器后面的T不要报错,是个通用的数据类型
void m_swap(T &a,T &b){
    int temp=a;
    a=b;
    b=temp;
}
template
void print_ab(T a,T b){
    cout<<"a:"< 

对于模板函数调用

    //自动推导
    m_swap(a,b);
    //显示指定类型
    m_swap(a,b);
案例

#include
#include
#include
#define random(x) rand()%(x)
using namespace std;
template
void mySwap(T &a,T &b){
    int temp=a;
    a=b;
    b=temp;
}
template//告诉编译器后面的T不要报错,是个通用的数据类型
//升序选择排序
void mySort(T a[],int len){
    for(int i=0;ia[j]){
                min=j;
            }
        }
        if(min!=i){
            swap(a[i],a[min]);
        }
    }
}
template
void print_arr(T a,int len){
    for(int i=0;i(a,10);
    mySort(b,10);
    print_arr(a,10);
    print_arr(b,10);

    return 0;
}

输出

9,4,6,2,0,2,5,3,3,2,
C,F,E,G,I,J,E,G,C,H,
-------------------
0,2,2,2,3,3,4,5,6,9,
C,C,E,E,F,G,G,H,I,J,


比如一个字符和int相加

  • 调用普通函数,会转换
  • 调用自动模板,会报错
  • 显示指定类型,会转换
普通函数和函数模板的调用规则

#include
using namespace std;
void myPrint(int a){
    cout<<"调用的是普通函数n";
}
template
void myPrint(T a){
    cout<<"调用的是函数模板n";
}
template
void myPrint(T a,T b){
    cout<<"调用的是重载的函数模板n";
}
int main(){
    int a=0;int b=1;
    char c='a';
    myPrint(a);//优先调用普通函数
    myPrint<>(a);//用空模板参数列表来强调调用函数模板
    myPrint(a,b);//调用重载的函数模板
    myPrint(c);//当函数模板能更好的匹配,优先调用函数模板
    return 0;
}

结果:

调用的是普通函数
调用的是函数模板
调用的是重载的函数模板
调用的是函数模板
模板的局限性

使用具体化的模板
#include
using namespace std;
class Person{
    public:
    Person(string name,int age){
        this->my_name=name;
        this->my_age=age;
    }
    string my_name;
    int my_age;
};
template
bool myCompare(T &a,T &b){
    if(a==b){
        return 1;
    }
    else{
        return 0;
    }
}
//具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
//具体化优先于常规模板
template<> bool myCompare(Person &a,Person &b){
    if(a.my_age==b.my_age&&a.my_name==b.my_name){
        return true;
    }
    else{
        return false;
    }
}
void test01(){
    int a=1,b=2;
    bool k=myCompare(a,b);
    if(k){
        cout<<"相等n";
    }
    else{
        cout<<"不相等n";
    }
}
void test02(){
    Person a("Tom",10);
    Person b("Tom",10);
    bool k=myCompare(a,b);
    if(k){
        cout<<"相等n";
    }
    else{
        cout<<"不相等n";
    }
}
int main(){
    test01();
    test02();
    return 0;
}
类模板
#include
using namespace std;
template
class Person{
    public:
    //别忘了构造函数的类型
    Person(NameType name,AgeType age){
        this->mName=name;
        this->mAge=age;
    }
    NameType mName;
    AgeType mAge;
    void showPerson(){
        cout<<"name:"<mName<<",age:"<mAge<p("tom",9);
    p.showPerson();
}
int main(){
    test();
    return 0;
}

总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板

类模板和函数模板的区别

#include
using namespace std;
template
class Person{
    public:
    Person(NameType name,AgeType age){
        this->mName=name;
        this->mAge=age;
    }
    NameType mName;
    AgeType mAge;
    void showPerson(){
        cout<<"name:"<mName<<",age:"<mAge<p("tom",9);
    p.showPerson();
}
void test01(){
    Personp("asd",8);
    p.showPerson();
}
void test02(){
    Personp("asd",'A');
    p.showPerson();
}
int main(){
    test();
    test01();
    test02();
    return 0;
}

其中带默认参数:

template
类模板中成员函数创造时机

#include
using namespace std;
class Person1{
    public:
    void showPerson1(){
        cout<<"This is person1n";
    }
};
class Person2{
    public:
    void showPerson2(){
        cout<<"This is person2n";
    }
};
template
class myClass{
    public:
    T obj;
    void fun1(){ obj.showPerson1();}
    void fun2(){ obj.showPerson2();}
};
void test01(){
    myClassp;
    p.fun1();
    //p.fun2() 编译出错
}
void test02(){
    myClassp;
    p.fun2();
}
int main(){
    test01();
    test02();
    return 0;
}
类模板对象做函数参数


补充:

#include
typeid(T).name()
#include
#include
#include
using namespace std;
template
class Person{
    public:
    Person(T1 name,T2 age){
        this->mName=name;
        this->mAge=age;
    }
    void ShowPerson(){
        cout<<"name:"<&p){
    p.ShowPerson();
}
void test01(){
    Personp("qzs",100);
    printPerson1(p);
}
//参数类型模板化
template
void printPerson2(Person&p){
    p.ShowPerson();
    cout<<"T1的类型为: "<p("zjh",18);
    printPerson2(p);
}
//整个类模板化,类模板配合函数模板
template
void printPerson3(T &p){
    p.ShowPerson();
    cout<<"T1的类型为: "<p("kkk",50);
    printPerson3(p);
}
int main(){
    test01();
    test02();
    test03();
    return 0;
}
类模板和继承

#include
#include
#include
using namespace std;
template
class base{
    T m;
};
//class son:public base 报错:缺少 类模板 "base" 的参数列表
class Son:public base{

};
void test01(){
    Son s1;
}
template
class Son2:public base{
    public:
    Son2(){
        cout<<"T1的数据类型为: "<s2;
};
int main(){
    test01();
    test02();
    return 0;
}

对于T,T1,T2的继承关系

类模板成员函数类外实现
#include
#include
#include
using namespace std;
template
class Person{
    public:
    Person(T1 name,T2 age);
    void ShowPerson();
    T1 mName;
    T2 mAge;
};
template
Person::Person(T1 name,T2 age){
    this->mName=name;
    this->mAge=age;
}

template
//返回类型+类名限定域+模板参数+函数名+参数
void Person::ShowPerson(){
    cout<<"name: "<mName<<" age:"<mAge<p("qzs",118);
    p.ShowPerson();
}
int main(){
    test01();
    return 0;
}

类模板成员函数,类外实现
要加:Person
返回类型+类名限定域+模板参数+函数名+参数

类模板分文件编写


基本都使用方法二:用hpp文件,#include"person.hpp",记住是".hpp"
person.hpp:

#pragma once
#include
using namespace std;
template
class Person{
    public:
    Person(T1 name,T2 age);
    void ShowPerson();
    T1 mName;
    T2 mAge;
};
template
Person::Person(T1 name,T2 age){
    this->mName=name;
    this->mAge=age;
}
template
void Person::ShowPerson(){
    cout<<"name :"<mName<<" age:"<mAge;
}

template.cpp:

#include
#include
#include
#include"person.hpp"//头文件要用""
using namespace std;

void test01(){
    Personp("qzs",100);
    p.ShowPerson();
}
int main(){
    test01();
    return 0;
}

其中补充:#pragma once的意思是防止多次包含

类模板和友元


函数模板类内实现:

#include
#include
#include
//#include"person.hpp"//头文件要用""
using namespace std;
template
class Person{
    //全局函数类内实现
    friend void ShowPerson1(Person &p){
        cout<<"类内name:"< &p);
    public://别忘了构造函数要放在public下,默认private
    Person(T1 name,T2 age){
        this->Name=name;
        this->Age=age;
    }
    private:
    T1 Name;
    T2 Age;
};
//全局函数类外实现
template
void ShowPerson2(Person &p){
    cout<<"类外name:"<p("qzs",100);
    ShowPerson1(p);
    ShowPerson2(p);
}
int main(){
    test01();
    return 0;
}

其中类外会报错:if this is not what you intended, make sure the function template has already been declared and add <> after the function name here
如果这不是你想要的,确保函数模板已经被声明并添加<>在函数名后
对于全局函数类外声明:

#include
#include
#include
using namespace std;
//再提前声明Person
template
class Person;
//提前声明
template
void ShowPerson2(Person &p){
    cout<<"类外name:"<
class Person{
    friend void ShowPerson2<>(Person &p);
    public://别忘了构造函数要放在public下,默认private
    Person(T1 name,T2 age){
        this->Name=name;
        this->Age=age;
    }
    private:
    T1 Name;
    T2 Age;
};

void test01(){
    Personp("qzs",100);
    ShowPerson2(p);
}
int main(){
    test01();
    return 0;
}

需要做到:
1.类内friend void ShowPerson2<>(Person &p)加<>
2.在类上定义函数
3.在函数上声明类

所以建议类内实现

类模板案例


遇到的一类错误,void的返回return不加0
对于MyArray.hpp

#pragma once
#include
using namespace std;
template
class MyArray{
    public:
    //有参构造
    MyArray(int capacity){
        //cout<<"MyArray的有参构造调用n";
        this->capacity=capacity;
        this->size=0;
        this->p=new T [this->capacity];
    }
    //拷贝函数
    MyArray(class MyArray &arr){
        //cout<<"MyArray的拷贝构造调用n";
        this->capacity=arr.capacity;
        this->size=arr.size;
        //this->p=arr.p; 浅拷贝,使不得
        this->p=new T[arr.capacity];
        for(int i=0;icapacity;i++){
            this->p[i]=arr.p[i];
        }
    }
    //析构函数
    ~MyArray(){
        //cout<<"MyArray的析构函数调用n";
        if(this->p!=NULL){
            delete []this->p;
            this->p=NULL;
        }
    }
    // operator 重载 防止浅拷贝
    MyArray& operator=(const MyArray& arr){
        //cout<<"MyArray的operator=调用n";
        //先判断堆区内存是否释放
        if(this->p!=NULL){
            delete []this->p;
            this->p=NULL;
            this->capacity=0;
            this->size=0;
        }
        //深拷贝
        this->p=new T[arr.capacity];//开的是和arr一样的大小
        this->capacity=arr.capacity;
        this->size=arr.size;
        for(int i=0;icapacity;i++){
            this->p[i]=arr.p[i];
        }
        return *this;
    }
    //尾插法
    void InsertTail(const T &val){
        //判断容量是否等于大小
        if(this->size==this->capacity){
            cout<<"满了n";
            return;
        }
        this->p[this->size]=val;
        this->size++;//size更新
    }
    //尾删法
    void DeleteTail(){
        if(this->size==0){
            cout<<"没元素可删了n";
            return;
        }
        this->size--;//物理删除不清0
    }
    //重载[],不然访问不到
    T& operator[](int index){ //返回一个引用类型 可以保证外部修改 arr[5]=100
        return this->p[index];
    }
    //返回数组容量
    int GetCapacity(){
        return this->capacity;
    }
    //返回数组大小
    int GetSize(){
        return this->size;
    }
    private:
    T *p;
    int capacity;
    int size;
};

对于main.cpp
提供了三个测试案例

#include
#include
#include
#include"MyArray.hpp"
#include
#include
using namespace std;
#define random(a,b) (rand()%((b)-(a)))+(a)

void test01(){
    //模板别忘了加
    MyArray arr1(5);
    MyArray arr2(arr1);
    MyArray arr3(100);
    arr1=arr3;
    arr1[5];
}
void PrintArr(MyArray &arr,int len){
    for(int i=0;iarr1(10);
    for(int i=0;i<5;i++){
        arr1.InsertTail(random(0,10));
    }
    PrintArr(arr1,5);
    cout<arr2(arr1);
    cout<<"arr2的打印输出"<name=name;
        this->age=age;
    }
    string name;
    int age;
};
void PrintPersonArray(MyArray&p){
    for(int i=0;iarr(10);
    arr.InsertTail(p1);
    arr.InsertTail(p2);
    arr.InsertTail(p3);
    arr.InsertTail(p4);
    arr.InsertTail(p5);
    PrintPersonArray(arr);
    cout<<"capacity:"<
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/291430.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号