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就是这种类型。
模版与友元函数
在模板类中声明友元函数,分四种类型。
- 不需要模板参数的非模板函数。
- 需要模板参数的非模板函数。
- 需要模板参数的模板函数,使用类模板参数特化。
- 需要模板参数的模板函数,自带模板参数。
- 需要模板参数的模板函数,自带多个模板参数。
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>;