C++学习之九

1)普通类的成员函数模板

class A
{
    
    
public:
    template<typename T> //类的成员函数模板,//成员函数模板和函数模板长得样子一样!
    void func(T tmp);
};

template<typename T>
void A::func(T tmp)
{
    
    
    cout << tmp << endl;
}

int main() 
{
    
    
    A a;
    a.func<double>(56.89);
    return 0;
}

2)模板类的成员函数模板

template<class T2>
class A
{
    
    
public:
    A(T2 arg):arg_(arg){
    
    }
    template<typename T> //类的成员函数模板
    void func(T tmp);
private:
    T2 arg_;
};

//模板类的成员函数模板类外定义方法
template<class T2>
template<typename T>
void A<T2>::func(T tmp)
{
    
    
    cout << tmp + arg_ << endl;
}

int main() 
{
    
    
    A<int> a1(45);
    a1.func<int>(45); //output 90
    return 0;
}

3)模板显式实例化,显式声明
显式实例化作用:为了防止多个.cpp文件生成相同的类模板,较少系统编译的开销;
实例化定义,实例化声明!
template A; //在多个.cpp文件中的其中任意一个文件中,实例化定义【只有一个】
extern template A; //在其他.cpp文件中,实例化声明【可以有多个】, 代表此文件不用在实例化
4)using定义模板别名(下面案例是定义map容器的类模板别名)
//using str_map_t = std::map<std::string, T> type;
//上面这句话,既不是函数模板,也不是类模板,是用using定义一个类型别名,也叫【类型模板】;

template<class T>
using str_map_t = std::map<std::string, T>; //类型模板,也叫模板别名

int main() 
{
    
    
    str_map_t<int> m1;
    m1.insert({
    
    "abc",123});
    return 0;
}

4.1)用typedef在模板类中,重新定义新的类型,但无法重新定义一个模板!!!using可以,定义的名字叫类型模板;
template //C++98之前的写法
struct A
{
typedef std::map<string, T> mapType; //必须有typedef,否则会编译错误
};
int main()
{
A::mapType a1;
a1.insert({ “first”,23 });
return 0;
}

//typedef int myint_t; //用typedef定义别名,就好像定义一个变量一样!!!
typedef int(func)(int, int);
using funcptr = int(
)(int, int); //有using定义一个函数指针的写法
5)显示指定模板参数

template<class T1,class T2,class T3>
T1 func(T2 a, T3 b)
{
    
    
    return a + b;
}

int main() 
{
    
    
    //auto ret = func(3, 6);这样写不行,因为T1没有类型,必须显示指定;
    auto ret = func<int>(3, 6);
    cout << ret << endl;
    return 0;
}

6)类模板全特化



说明:
	必须有泛化版本,才可以有特化版本!!!
 	特化版本优先被编译;

template<class T> //泛化版本
class A
{
    
    
public:
    bool compare(const T& tmp)
    {
    
    
        cout << "一般模板" << tmp << endl;
        if (tmp > 2.5) return 1;
    }
};

template<>
class A<float> //全特化版本,注意float绑定到类A上,注意写法!!!
{
    
    
public:
    bool compare(const float& tmp)
    {
    
    
        cout << "全特化" <<tmp << endl;
        if (tmp > 2.5) return 1;
    }
};

int main() 
{
    
    
    A<float> a;
    a.compare(4.7); //调用全特化版本
    A<int> a2;
    a2.compare(40); //泛化版本
    return 0;
}

7)特化成员函数而不是模板



注意:特化成员函数就一个类,这是跟模板类特化的重要区别!!!
class A
{
    
    
public:
    template<typename T>
    void func(T tmp);
};

template<typename T> //成员函数的泛化版本
void A::func(T tmp)
{
    
    
    cout << "成员函数的泛化版本 " << tmp << endl;
}

template<> //成员函数的特化版本
void A::func(int tmp)
{
    
    
    cout << "成员函数的特化版本 " << tmp << endl;
}

int main() 
{
    
    
    A a;
    a.func<>(6); //调用的是特化版本
    a.func<float>(5.3); //调用的是泛化版本
    return 0;
}

8)类模板偏特化(也就局部特化)

//偏特化两方面:1)从模板参数数量上;2)模板参数范围上
template<class T,class U,class W>
class A //泛化类模板
{
    
    
public:
    A() {
    
     cout << "泛化版本 A constructor" << endl; }
    void func(void){
    
     cout << "泛化版本 func" << endl; }
};

template<class U,class W>
class A<int,U,W>
{
    
    
public:
    A() {
    
     cout << "偏特化版本1 A constructor" << endl; }
    void func(void) {
    
     cout << "偏特化版本1 func" << endl; }
};

template<class T, class W>
class A<T, float, W>
{
    
    
public:
    A() {
    
     cout << "偏特化版本2 A constructor" << endl; }
    void func(void) {
    
     cout << "偏特化版本2 func" << endl; }
};

int main() 
{
    
    
    A<char,int,int> a1; 
    a1.func();//调用的是泛化版本

    A<int, int, int> a2;
    a2.func();//调用的是特化版本1
    return 0;
}

9)函数模板全特化,函数模板没有偏特化






template<typename T,typename U>
void func(T a, U b)
{
    
    
    cout << "函数模板泛化 " << a + b << endl;
}

//以下5句代码用于不会执行!!!
template<typename T>
void func<T, double>(T a, double b) //函数模板偏特化,这是不可以的,编译不过去!!!!!!!!
{
    
    
    cout <<"函数模板偏特化--------------- "<< a + b << endl;
}

template<>
void func<double,double>(double a, double b) //必须有“<double,double>”,如果没有,则本质上是函数重载;
{
    
    
    cout << "函数模板全特化--- " << a + b << endl;
}


int main() 
{
    
    
    func<int,int>(3, 4.7); //调用的是泛化版本
    func<int,double>(4, 2.7);
    func<>(3.4, 5.6);//调用的是全特化版本
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30143193/article/details/132443773