意思就是类模板中吧类模板当做成员函数或者类成员
直接上代码吧
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
template<typename T>
class beta
{
private:
template <typename V>
class hold
{
private:
V val;
public:
shold(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 (n.Value() + q.Value()) * u /t;}
void Show() const { q.show(); n.show();}
};
int main()
{
beta<double> guy(3.5, 3);
cout << "T was set to double\n";
guy.Show();
cout << "V was set to T, which is double, then V was set to int\n";
cout << guy.blab(10, 2.3) << endl;
cout << "U was set to int\n";
cout << guy.blab(10.0, 2.3) << endl;
cout << "U was set to double\n";
cout << "Done\n";
return 0;
}
C++允许外部定义成员模板。但不是所有的编译器都支持。 如果不支持的话就算了 支持的话可以这么写:
将模板用于参数:
先上代码在说话
stacktp.h
#ifndef STACKTP_H_
#define STACKTP_H_
template<class Type>
class Stack
{
private:
enum {MAX = 10};
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item);
bool pop(Type & item);
};
template<class Type>
Stack<Type>::Stack()
{
top = 0;
}
template<class Type>
bool Stack<Type>::isempty()
{
return top == 0;
}
template<class Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template<class Type>
bool Stack<Type>::push(const Type & item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
{
return false;
}
}
template<class Type>
bool Stack<Type>::pop(Type & item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
#endif
tempparm.cpp
#include <iostream>
#include "stacktp.h"
template <template <typename T> class Thing>
class Crab
{
private:
Thing<int> s1;
Thing<double> s2;
public:
Crab() {};
bool push(int a, double x) {return s1.push(a) && s2.push(x);}
bool pop(int & a, double & x) {return s1.pop(a) && s2.pop(x);}
};
int main() {
using std::cout;
using std::cin;
using std::endl;
// 这时候 Thing形参就是 模板Stack类型 在默认构造函数的时候就生成int型的Stack模板和double型的Stack模板
Crab<Stack> nebula;
int ni;
double nb;
cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
while(cin >> ni >> nb && ni > 0 && nb > 0)
{
if (!nebula.push(ni, nb))
break;
}
while (nebula.pop(ni, nb))
cout << ni << ", " <<nb << endl;
cout << "Done.\n";
return 0;
}
运行结果:
模板类和友元:
模板类可以有友元, 但是有3种友元
1. 非模板友元
2. 约束模板友元
3.非约束模板友元
一个一个来
非模板友元
template <class T>
class A
{
public:
friend void counts();
}
counts()是模板所有实例化对象的友元。 这是不带参数的例子。它可以访问全局对象,可以使用全局指针访问的费全局对象。可以创建自己的对象。 可以访问独立于对象的模板类的静态数据成员。
那如果要带参数呢 而且是要带模板类参数呢?
但需要指明特定类型的对象 比如:
template <class T>
class A
{
public:
friend void counts(A<T> &);
}
这样将counts将称为A<T>类的友元。
程序示例:
#include <iostream>
using std::cout;
using std::endl;
template <typename T>
class HasFriend
{
private:
T item;
static int ct;
public:
HasFriend(const T & i) : item(i) {ct++;}
~HasFriend() {ct--;}
friend void counts();
friend void reports(HasFriend<T> &);
};
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 delared: ";
counts();
HasFriend<int> hfi1(10);
cout << "After hfil declared: ";
counts();
HasFriend<int> hfi2(20);
cout << "After hfi2 declared: ";
counts();
HasFriend<double> hfdb(10.5);
cout << "AFter hfdb delared: ";
counts();
reports(hfi1);
reports(hfi2);
reports(hfdb);
return 0;
}
运行结果
2.约束模板友元函数
就是把友元函数先声明为函数模板 然后在类模板中定义的是该函数模板
程序示例:
#include <iostream>
using std::cout;
using std::endl;
template<typename T> void counts();
template<typename T> void report(T &);
template <typename TT>
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i) : item(i) {ct++;}
~HasFriendT() {ct--;}
friend void counts<TT>();
friend void report<>(HasFriendT<TT> &);
};
template<typename T>
int HasFriendT<T>::ct = 0;
template<typename T>
void counts()
{
cout << "template size: " << sizeof(HasFriendT<T>) << "; ";
cout << "template counts(); " << HasFriendT<T>::ct << endl;
}
template <typename T>
void report(T & hf)
{
cout << hf.item << endl;
}
int main()
{
counts<int>();
HasFriendT<int> hfi1(10);
HasFriendT<int> hfi2(20);
HasFriendT<double> hfdb(10.5);
report(hfi1);
report(hfi2);
report(hfdb);
cout << "counts<int>() output:\n";
counts<int>();
cout << "counts<double>() output:\n";
counts<double>();
return 0;
}
运行结果
3.非约束模板友元函数
模板类型放开 ,不用跟着模板类型走:
示例:
#include <iostream>
using std::cout;
using std::cin;
template <typename T>
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T & i) : item(i) {}
template<typename C, typename D> friend void show2(C &, D &);
};
template<typename C, typename D> void show2(C & c, D & d)
{
cout << c.item << ", " << d.item << '\n';
}
int main()
{
ManyFriend<int> hfi1(10);
ManyFriend<int> hfi2(20);
ManyFriend<double> hfdb(10.5);
cout << "hfi1, hfi2: ";
show2(hfi1, hfi2);
cout << "hfdb, hfi2: ";
show2(hfdb, hfi2);
return 0;
}
运行结果
大体区别就是
非模板的友元: 没有跟着哪个类 就是跟某个实例对象友元。
约束模板函数: 就是跟某个类型的模板关联。
非约束模板函数: 不限制某个类型的模板, 因为定义了另外的两个模板参数。所以可以传入不同类型的模板作为参数。
然后目前来说。好像没啥卵用。
模板别名:
可以这样定义别名:
typedef std::array<int, 12> arri;
C++11 可以这样:
template<typename T>
using arrtype = std::array<T, 12>;
然后可以这么干:
arrtype<double> gallons;
arrtype<int> days; == array<int , 12>
这种定义别名的方式也适用于非模板
优点: 可读性更强,因为它让类型名和类型信息更清晰。
总结:
第十四章 真 • 完结