c++模板类

嵌套模版

template<typename T>
class out
{
private:
    class inter
    {
    private:
        T value;
    public:
        inter();
    };
};
template<typename T>
out<T>::inter::inter()
{}
template <typename T>
class out
{
private:
    template <typename C>
    class inter
    {
        C value;
    public:
        inter();
    };
};
template <typename T>
    template <typename C>
    out<T>::inter<C>::inter()
    {}

将模版作为参数

template < template<typename T>class Thing >
class crab
{};
template <typename T>
class King
{}

  上面template<typename T>clas是类型,Thing是指这种类型的别名,King就是这种类型。

模版与友元函数

在模板类中声明友元函数,分四种类型。

  1. 不需要模板参数的非模板函数。
  2. 需要模板参数的非模板函数。
  3. 需要模板参数的模板函数,使用类模板参数特化。
  4. 需要模板参数的模板函数,自带模板参数。
  5. 需要模板参数的模板函数,自带多个模板参数。
template <typename V>
class A;
template <typename V>
void f3(A<V>& a);

template <typename T>
class A
{
public:
	friend void f1();	
	friend void f2(A<T>& a);
	friend void f3<T>(A<T>& a);
	template <typename U>
	friend void f4(A<U>& a);
    template<typename C,typename D>
    friend void f5(C &a,D &b);
};

非模板的友元函数

不需要模板参数

  上面的f1是A<int>,A<double>等的友元函数,也就是无论多少种实例,都只有一个函数。它可以访问①全局对象,②通过全局指针访问非全局对象,③访问类的静态函数。

#include <iostream>
using namespace std;
template <typename T>
class A
{
private:
    static int num;
public:
    A(){++num;}
    ~A(){--num;}
    friend void f1();
};
template<typename T>
int A<T>::num = 0;
void f1()
{
    cout << A<int>::num << "\t" << A<double>::num << endl;
}
int main()
{
    A<int> a,b,c;
    A<double> d,e;
    f1();
    return 0;
}

需要模板参数

  f2(A<int> &)A<int>的友元函数,但不是A<double>的友元函数,也就是说每种类型的实例都会有一个f2之对应。但是如果想在类外为f2友元函数写定义,只能直接为每一种特化后的参数写一个。在类内写定义会随着类的实例化自动生成对应的函数。

#include <iostream>
using namespace std;
template <typename T>
class A
{
private:
    static int num;
    T value;
public:
    A(const T &n):value(n){++num;}
    ~A(){--num;}
    friend void f2(A<T> &a);//类外定义,需要每种类型都定义
    friend void f2_2(A<T> &a)//类内定义,自动生成函数
    {
        cout << "f2_2: " << a.value << endl;
    }
};
template<typename T>
int A<T>::num = 0;
void f2(A<int> &a)
{
    cout << "f2: " << a.value << endl;
    //cout << A<double>::num  << endl;,说明f2(A<int> &a)无法访问A<double>的数据
}
int main()
{
    A<int> a(9);
    A<double> d(9.9);
    f2(a);
    //f2(d);//undefined reference to `f2(A<double>&)'
    f2_2(a);
    f2_2(d);
    return 0;
}

模版的友元函数

使用类模板参数特化

#include <iostream>
using namespace std;
template <typename V>
class A;
//在类的前面声明模板函数
template <typename V>
void f3(A<V>& a);
template <typename T>
class A
{
private:
    static int num;
    T value;
public:
    A(const T &n):value(n){++num;}
    ~A(){--num;}
    friend void f3<T>(A<T>& a);//可以写为friend void f3<>(A<T> &a),编译器会自动推导那个T
};
template<typename T>
int A<T>::num = 0;
template <typename T>
void f3(A<T> &a)
{
    cout << "f3: " << a.value << endl;
}
int main()
{
    A<int> a(9);
    A<double> d(9.9);
    f3(a);
    f3(d);
    return 0;
}

  f3(A<int>)A<int>的友元,但不是A<double>的友元,也就是说每种类型的实例都会有一个f3之对应。
  与f2的区别。

  • f2不需要模板参数推导,相比f3是更优的匹配,两者同名时会优先调用f2。
  • f3在类外定义时无需像f2那样,一个个定义。

自带模板参数

自带单个模板参数

#include <iostream>
using namespace std;
template <typename V>
class A;
template <typename V>
void f3(A<V>& a);

template <typename T>
class A
{
private:
    T value;
    static int num;
public:
    A(const T &n):value(n){++num;}
    ~A(){--num;}
	friend void f3<T>(A<T>& a);
	template <typename U>
	friend void f4(A<U>& a);
};
template<typename T>
int A<T>::num = 0;

template <typename T>
void f3(A<T> &a)
{
    cout << "f3: " << a.value << endl;
}

template <typename U>
void f4(A<U> &a)
{
    cout << "f4: " << a.value << endl;
}

int main()
{
    A<int> a(9);
    A<double> d(9.9);
    f3(a);
    f4(a);
	return 0;
}

  这样开起来f3和f4是没有区别的。由于f4中的函数模板参数不一定是跟类的模板参数一样,所以f4(A<int>)f4(A<double>)可以是A<int>的友元,也可以是A<double>的友元。下面例子可以说明。

#include <iostream>
using namespace std;
template <typename V>
class A;
template <typename V>
void f3(A<V>& a);

template <typename T>
class A
{
private:
    T value;
    static int num;
public:
    A(const T &n):value(n){++num;}
    ~A(){--num;}
	friend void f3<T>(A<T>& a);
	template <typename U>
	friend void f4(A<U>& a);
};
template<typename T>
int A<T>::num = 0;

template <typename T>
void f3(A<T> &a)
{
    cout << "f3: " << A<double>::num << endl;
}

template <typename U>
void f4(A<U> &a)
{
    cout << "f4: " << A<double>::num << endl;
}

int main()
{
    A<int> a(9);
    A<double> d(9.9),e(1.9);
    f3(a);//调用出现错误
    f4(a);
	return 0;
}

自带多个模板参数

#include <iostream>
using namespace std;
template <typename T>
class A
{
private:
    T value;
public:
    A(const T &n):value(n){}
    ~A(){}
    template <typename C,typename D>
    friend void f5(A<C> &c,A<D> &d);
};
template <typename C,typename D>
void f5(A<C> &c,A<D> &d)
{
    cout << c.value << '\t' << d.value << endl;
}
int main()
{
    A<int> a(9);
    A<double> d(9.9);
    f5(a,d);
	return 0;
}

模版别名

typedef array<int,13> myarray;
using myarray = array<int,13>;
template <typename T>
using myarray = array<T,13>;
posted @ 2018-04-10 22:57  h_hg  阅读(285)  评论(0编辑  收藏  举报