(C++)模板

目录

一、函数模板

1、函数模板的概念

2、函数模板的语法

3、模板函数调用方式

4、函数模板的使用

二、类模板

1、类模板的概念

2、类模板的语法

3、类模板的使用

4、模板的继承

5、模板中关于函数的声明

6、模板中的static

练习:改错


一、函数模板

1、函数模板的概念

概念:c++提供的函数模板机制,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来表示,这个通用的函数称为模板函数

2、函数模板的语法

格式:

template<类型形式参数表>

类型 函数名(形式参数表)

{

代码块

}

//当模板函数和普通函数同时存在,优先调用普通函数

3、模板函数调用方式

(1)隐式调用

//不写入的参数类型,让编译器自己判断传入的是什么类型的数据

//模板函数不能自动发生隐式类型转换

int  n1 = 100,  n2 = 200;

Swap(n1,  n2);              //隐式调用

(2)显示调用

格式:

函数名<类型列表>  (实参列表)

//在调用时说明传入的类型参数

Swap<char>(c1,  c2);        //显示调用

4、函数模板的使用

#include <iostream>
using namespace std;
/*int add(int x,int y)   //当模板函数和普通函数同时存在,优先调用普通函数
{
    cout<<"普通函数"<<endl;
    return x + y;
}*/
/*double add(double x,double y)
{
    return x + y;
}*/
template <typename T>  //声明虚拟类型T,作用范围到这个函数结束
T add(T x, T y)
{
    return x + y;
}

template <typename T1,typename T2>
void print(T1 x,T2 y)
{
    cout<<x<<" "<<y<<endl;
}
int main(int argc, char const *argv[])
{
    int a = 100,b = 200;
    double c = 4.32,d = 9.789;

    cout<<add(a,b)<<endl;
    cout<<add(c,d)<<endl;
    //cout<<add(1,2.222)<<endl;  //模板函数不能进行隐式类型转换   隐式调用
    cout<<add<int>(1,2.222)<<endl;  //显示调用
    
    print(a,d);
    print<double,char>(1.11,97);
    return 0;
}

二、类模板

1、类模板的概念

类模板中定义的函数类型可以用在类声明和类实现中,类模板的目的是将数据的类型参数化。

2、类模板的语法

template <typename 类型参数1, typename 类型参数2>

class 类型{

.......

}

//类模板创建对象一定要显示调用

3、类模板的使用

#include <iostream>
using namespace std;
template <typename T,typename U>
class Test
{
    private:
        T a;
        U b;
    public:
        Test(T a, U b)
        {
            this->a = a;
            this->b = b;
        }
        void show()
        {
            cout<<a<<" "<<b<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Test<int,char> t(1,'a');   //类模板创建对象一定要显示调用
    t.show();
    return 0;
}

4、模板的继承

//模板类派生普通类,继承的同时对基类进行实列化(指明基类的具体类型)

//模板类派生模板类,继承时可以不需要对基类进行实列化(基类类型可以不指明)

#include <iostream>
using namespace std;
template <typename T>
class Parent
{
    protected:
        T a;
    public:
        Parent(T a)
        {
            this->a = a;
        }
        void show()
        {
            cout<<"a = "<<a<<endl;
        }
};
class Child:public Parent<int>     //模板类派生普通类,继承的同时对基类实例化
{
    public:
        Child(int a):Parent<int>(a)     //构造函数同样需要实例化
        {

        }
        void show()
        {
            cout<<"a = "<<a<<endl;
        }
};
template <typename F,typename U>
class Child2:public Parent<F>    //模板类派生模板类,继承的同时不需要对parent实例化
{
    private:
        U b;
    public:
        Child2(F a,U b):Parent<F>(a)
        {
            this->b = b;
        }
        void show()
        {
            cout<<this->a<<" "<<b<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Child c1(2);
    c1.show();
    Child2<int,double> c2(1,2.222);
    c2.show();

    return 0;
}

5、模板中关于函数的声明

//函数在类外部时,需要重写模板

#include <iostream>
using namespace std;
template <typename T,typename U>
class Test
{
    private:
        T a;
        U b;
    public:
        Test(T a, U b);
        void show();
 
};
template <typename T,typename U>
Test<T,U>::Test(T a, U b)
{
    this->a = a;
    this->b = b;
}
template <typename T,typename U>
void Test<T,U>::show()
{
    cout<<a<<" "<<b<<endl;
}
int main(int argc, char const *argv[])
{
    Test<int,char> t(1,'a');   //类模板创建对象一定要显示调用
    t.show();
    return 0;
}

6、模板中的static

//类中的 static 修饰的变量,需要在类外部进行初始化

//成员变量在初始化之前,需要重写模板

//static 修饰的成员变量,按模板进行分配,换句话说,相同的模板,用的是同一个static 成员变量

#include <iostream>
using namespace std;
template <typename T,typename U>
class Test
{
    private:
        T a;
        U b;
    public:
        static int count;
    public:
        Test(T a, U b);
        void show(); 
};
template <typename T,typename U>
int Test<T,U>::count = 0;

template <typename T,typename U>
Test<T,U>::Test(T a, U b)
{
    this->a = a;
    this->b = b;
    count++;
}

template <typename T,typename U>
void Test<T,U>::show()
{
    cout<<a<<" "<<b<<endl;
}
int main(int argc, char const *argv[])
{
    Test<int,char> t1(1,'a');
    Test<int,char> t2(1,'a');
    Test<int,char> t3(1,'a');
    Test<int,char> t4(1,'a');
    Test<int,char> t5(1,'a');

    Test<int,double> t6(1,1.11);
    Test<int,double> t7(2,1.11);
    Test<int,double> t8(3,1.11);

    cout<<Test<int,char>::count<<endl;     //count = 5
    cout<<Test<int,double>::count<<endl;   //count = 3

    return 0;
}

练习:改错

#include <stdio.h>
struct test{
    int a;
    int b;
};
void func(struct  test *tt)
{
    struct test *lt;
    lt = &tt[0];
    printf("[0] a : %d,b:%d\n",lt->a,lt->b);
    lt = &tt[1];
    printf("[1] a : %d,b:%d\n",lt->a,lt->b);
    lt = &tt[2];
    printf("[2] a : %d,b:%d\n",lt->a,lt->b);
    return;
};
int main(int argc, char const *argv[])
{
    struct test lm[3] = {{1,2},{11,22},{111,222}};
    struct test llm = {333,444};
    func(lm);
    func(&llm);
    return 0;
}

上述代码,错误在于数组作为函数传参时,需要传两个方面的值:数组首地址、数组大小;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值