struct A {
void showA();
};
struct B {
void showB();
};
template <typename T>
struct Show {
void func1() {
obj.showA();
}
void func2() {
obj.showB();
}
T obj;
};
为了保证上述代码中类模板能够在如下代码中成功执行,成员函数在被调用前不会被创建。普通成员函数在调用前已经被创建。
Show<A> s;
s.func1();
s.func2(); // error
template <typename T1, typename T2>
class AA {
public:
AA(T1 n, T2 m)
: _n(n), _m(m) {}
T1 _n;
T2 _m;
};
一共有三种传参方式
- 指定传入类型
void func(AA<int, double>& obj);
- 参数模板化
template <typename T1, typename T2> void func(AA<T1, T2>& obj);
- 整个类模板化
拓展一点,我们还可以写个模板模板参数(C++17)
template <typename T> void func(T& obj);
template <typename T1, typename T2, template <typename T1, typename T2> class C> void func(C<T1, T2>& obj);
当我们调用函数时,以上三(+1)种调用方式都可以实现传参
AA<int, double>a(10, 9.9);
func(a);
实际开发中,我们更常用第一(四)种传参方式
当子类继承的基类是一个模板类时,子类在声明的时候要指定出基类中T的类型。如果不指定,编译器无法给子类分配内存。
template<typename T>
class Base {
T m;
};
class Derived : public Base<int> {};
如果想灵活指定基类中T类型,子类也需要变成类模板
template<typename T1, typename T2>
class Derived : public Base<T2> {
T1 obj;
};
通过全局函数做友元(类内实现)访问类内成员
template<typename T1, typename T2>
class AA {
friend void show(AA<T1, T2>a) {
std::cout << a._n << a._m << std::endl;
}
T1 _n;
T2 _m;
public:
AA(int n, int m)
: _n(n), _m(m) {}
};
通过全局函数做友元(类外实现)访问类内成员
template<typename T1, typename T2>
class AA; // 声明存在类AA
template<typename T1, typename T2>
void show(AA<T1, T2>a) { // 函数提前声明并定义
std::cout << a._n << a._m << std::endl;
}
template<typename T1, typename T2>
class AA {
// 加空模板参数列表强制调用模板函数
friend void show<>(AA<T1, T2>a);
T1 _n;
T2 _m;
public:
AA(int n, int m)
: _n(n), _m(m) {}
};
edit Serein