主题
C++类模板
模板形式
c++
// 定义模板
template <typename T>
class ClassName {
private:
T m_data;
public:
ClassName(T);
}
// 实现模板
template <typename T>
ClassName<T>::ClassName(T t)
{
m_data = t;
}
// 使用模板类
ClassName<int> cn(1);c++
template <typename T, int n>
class ClassName2 {}c++
// 参数可带默认类型
template <typename T1, typename T2 = int>
class ClassName3 {}模板可以作为基类,也可用作组件类,还可用作其他模板的类型参数。
提示
通常将模板的声明和定义放到同一个头文件中。
具体化
同函数模板,类模板的具体化也分为隐式实例化、显式实例化和显式具体化。
c++
// 编译器在需要对象之前,不会生成类的隐式实例化
ClassName2<int, 10> * ptr; // 指针,还不需要对象,此步骤不会生成类
ptr = new ClassName2<int, 10>; // 编译器将生成类定义,并根据该定义创建对象c++
// 虽没有创建或提及类对象,编译器也将生成类声明(包括方法定义)
template class ClassName2<string, 10>;c++
// 显式具体化的类模板定义,对特定类型,类模板有不同的行为(与函数模板用意相同)。
template <> class ClassName<char*> {};c++
// 假设有一个通用的类模板定义
template <typename T1, typename T2> class TestClass {};
// 指定部分类型参数的类型,如指定T2为int类型
template <typename T1> class TestClass<T1, int> {};成员模板
模板可以作为结构体、类或模板类的成员。
c++
template <typename T>
class Beta
{
private:
template <typename V> // 嵌套模板作为模板类的成员
class Hold
{
private:
V val;
public:
Hold(V v=0): val(v) {}
void show() const { cout << val << endl; }
V value() const { return val; }
};
Hold<T> q;
Hold<int> n;
public:
Beta(T t, int i): q(t), n(i) {}
template<typename U> // 模板方法
U blab(U u, T t) { return (q.value() + n.value()) * u / t; }
void show() const { q.show(); n.show(); }
};c++
template<typename T>
class Beta
{
private:
template <typename V>
class Hold;
Hold<T> q;
Hold<int> n;
public:
Beta(T t, int i) : q(t), n(i) {}
template<typename U>
U blab(U u, T t);
void show() const { q.show(); n.show(); }
};
template <typename T>
template <typename V>
class Beta<T>::Hold
{
private:
V val;
public:
Hold(V v = 0) : val(v) {}
void show() const { cout << val << endl; }
V value() const { return val; }
};
template <typename T>
template <typename U>
U Beta<T>::blab(U u, T t)
{
return (n.value() + q.value()) * u / t;
}模板作为参数
c++
template <template <typename T> typename U, typename V>
class Crab {
private:
U<int> s1;
}
// ...
Crab<ClassName, int> c1;U作为模板的参数,其本身也是一个类模板,类U模板的的声明是template <typename T>,实例对象c1中的ClassName模板类要符合此声明。U<int>将被替换成ClassName<int>。
模板类和友元
- 非模板友元:在模板类中将一个常规函数声明为友元。
- 约束模板友元:友元的类型取决于类被实例化时的类型,即类模板的参数类型作为友元函数模板参数类型的一部分。
- 非约束模板友元:友元的所有具体化都是类的每一个具体化的友元,即类模板的参数类型和友元函数模板的参数类型无关。
c++
template <typename T>
class HasFriend
{
public:
HasFriend(const T& t) : item(t) { ct++; }
~HasFriend() { ct--; }
friend void counts();
friend void reports(HasFriend<T>&);
private:
T item;
static int ct;
};
template <typename T>
int HasFriend<T>::ct = 0;
void counts()
{
cout << "int count: " << HasFriend<int>::ct << ";";
cout << "double count: " << HasFriend<double>::ct << endl;
}
void reports(HasFriend<int>& hf)
{
cout << "HasFriend<int>: " << hf.item << endl;
}
void reports(HasFriend<double>& hf)
{
cout << "HasFriend<double>: " << hf.item << endl;
}
int main()
{
cout << "No Objects declared: ";
counts();
HasFriend<int> hfi1(10);
cout << "After hfi1 declared: ";
counts();
HasFriend<int> hfi2(20);
cout << "After hfi2 declared: ";
counts();
HasFriend<double> hfdb(10.5);
cout << "After hfdb declared: ";
counts();
reports(hfi1);
reports(hfi2);
reports(hfdb);
}c++
template <typename T> void counts();
template <typename T> void reports(T&);
template <typename TT>
class HasFriend
{
public:
HasFriend(const TT& t) : item(t) { ct++; }
~HasFriend() { ct--; }
friend void counts<TT>();
friend void reports<HasFriend<TT>>(HasFriend<TT>&);
private:
TT item;
static int ct;
};
template <typename T>
int HasFriend<T>::ct = 0;
template <typename T>
void counts()
{
cout << "template size: " << sizeof(HasFriend<T>) << endl;
cout << "template counts: " << HasFriend<T>::ct << endl;
}
template <typename T>
void reports(T& hf)
{
cout << hf.item << endl;
}
int main()
{
counts<int>();
HasFriend<int> hfi1(10);
HasFriend<int> hfi2(20);
HasFriend<double> hfdb(20.5);
reports(hfi1);
reports(hfi2);
reports(hfdb);
cout << "counts<int>() output: ";
counts<int>();
cout << "counts<double>() output: ";
counts<double>();
}c++
template <typename T>
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T& t): item(t) {}
template <typename C, typename D> friend void show(C&, D&);
};
template <typename C, typename D> void show(C& c, D& d)
{
cout << c.item << ", " << d.item << endl;
}
int main()
{
ManyFriend<int> hfi1(10);
ManyFriend<int> hfi2(20);
ManyFriend<double> hfdb(20.5);
show(hfi1, hfi2);
show(hfdb, hfi2);
}