Day

Day,第1张

Day 1.模板函数

        什么是模板 : 把类型当做未知量,可以忽略类型影响

        什么是模板函数:被 template 或者 template 修饰的函数就是模板函数。

        (1).普通模板函数

        template 相当于创建一个新的位置变量_Ty,且_Ty可以被修饰的函数使用。

template 
void prrint(_Ty one){

}

        也可以把他们写到同一行中,只不过不太美观

template  void prrint(_Ty one){

}

         模板函数可以显式调用,也可以隐式调用。显式调用需要尖括号(< >)给_Ty未知类型赋予一个类型。隐式调用则会根据函数的参数来自动推段类型。

//显式调用 需要说明对应的类型
print(string("xxx"));
//隐式调用 自动根据参数来判断类型
print("xxx");

      (2).类的成员函数是模板函数
class MM{
public:
    MM() = default;
    MM(string name,int age):name(name),age(age){
    
    }
    template 
    void print(_Ty one);    //申明模板函数
protected:
    string name;
    int age;
};

//类外实现模板函数
template 
void MM::print(_Ty one){
    cout << one << endl;
}
int main(){
    MM mm;
    mm.print("ILoveYou");//显式调用类中的模板函数
    mm.print(12);                //隐式调用类中的模板函数

    return 0;
}
(3).函数模板重载

        1)普通函数被模板函数重载

        模板函数可以和普通函数名重名。但这时候调用函数时到底调用的是普通函数,函数模板函数呢?

        首先,通过显示调用,毫无疑问调用的是模板函数。但是通过隐式调用时,是优先调用普通函数,还是模板函数呢? 答案是优先调用普通函数(形参实参类型一致的情况下)

//模板函数
template 
void print(_Ty one){
    cout << one << endl;
}
//普通函数
void print(int one){
    cout << one << endl;
}
int main(){
    print("xxx"); //毫无疑问调用模板函数
    print(10);            //调用普通函数
    print("xxx");         //调用模板函数
    reutrn 0;
}
        2).模板函数被模板函数重载

        函数模板重载函数模板时,该调用哪个函数。应该优先调用类型相似度高的。

template 
void print(_Ty1 one, _Ty2 two){
    cout << one << endl;
    cout << two << endl;
}

template 
void print(_Ty one, _Ty two){
    cout << one << endl;
    cout << two << endl;
}
int main(){
    
    print(12,12);        //优先调用一个类型的
    print(12,"xx");      //优先调用两个类型的
    print(12,12)    //传入了两个参数给未知类型,所以一定调用的是两个类型的 


    return 0;
}

        

2.模板类        (1).模板类创建

        只要被template修饰就是一个模板类,不管有没有使用未知类型。template 修饰

而且,模板类必须显示调用 (类名<类型>)

template 
class MM{
public:

protected:
};

        注:模板类不是一个完整的类,所以在使用到模板类的时候必须要   类名<类型>  配合使用, 尤其注意 模板类中成员函数 和 成员模板函数 类外实现的写法。

template 
class MM{
public:
    void print();
    template 
    void print();
protected:
};

//模板类的成员函数类外实现
template 
void MM::<_Ty> print(){

}

//模板类的成员模板函数类外实现
template 
template 
void MM<_Ty> print(){

}

int main(){
    MM m;    //创建对象时 类名也要 写成 类名<类型>的形式
    m.print();

    reutrn 0;
}
         (2).模板类继承

        模板类的继承,子类也需要template修饰(代码举例一个普通类继承模板类)

template 
class MM {				//只要被template修饰 就是模板类 不管有没有用未知类型
public:
	MM() = default;
	MM(string name) :name(name) {

	}
	void print();
protected:
	string name;
};

//普通类继承模板类
template 
class Girl :public MM<_Ty> {
public:
	Grit(string name) :MM<_Ty>(name) {

	}
protected:
};
        (3).模板类特化

               用于处理一些自定义的特殊类型和折叠参数

                1)局部特化

                        模板类n个类型特化成n-1个类型或者更少。 特化后的类,需要template<>修饰,且类名仍需要:类名<类型> 。特化后用到哪个未知类型,template中就写哪个未知类型。

        类名<类型> 中, 类型的个数要和模板类一致。

//模板类
template 
class MM{
public:

protected:

};
//两个未知类型特化成一个类型
template 
class MM<_Ty,_Ty>{
public:

protected:

};

                局部特化可以处理模板类不方便处理的自定义数据类型。

class Data{
public:
    Data(int a,int b):a(a),b(b){}
    void print(){
    cout<
class MM{
public:
    MM(_Ty1 one,_Ty2 two):one(one),two(two){};
    void print(){
            cout< 

        若是用 Data 类的对象来做上述模板类 MM 的未知类型。在不做运算符重载的情况下,是没有办法直接流运算符输出的。

        但是我们通过局部特化,就可以通过 Data 类对象的 print() 方法来输出。

//局部特化来处理 Data 类的对象
template 
class MM<_Ty,_Ty>{
public:
    MM(_Ty one,_Ty two):one(one),two(two){}
    void print(){
        one.print();
        two.print();
    }
protected:
    _Ty one;
    _Ty two;
};

        注:模板类也可以通过 Data 类对象的 print() 方法来输出,但是对于其他普通类型的数据就不适用了。相当于专门特殊化一个类,来处理特殊类型数据。

                2)完全特化

                完全特化 :模板类中已经没有未知类型了,都已经具体化了,但它仍是模板类。

                需要template <> 修饰 ,但是已经没有未知类型了,所以尖括号中不用写类型,类名<类型>中,要写清楚所有的类型。

//完全特化
template <>
class MM {
public:
	MM(string one, string two) :one(one), two(two) {}
	void print() {
		cout << one << " " << two << endl;
	}
protected:
	string one;
	string two;
};

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5658455.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-16

发表评论

登录后才能评论

评论列表(0条)

    保存