1 类模板与继承
-- 类模板从类模板派生(mubanpaisheng1.cpp)
/**
* 类模板从类模板派生
*/
#include <iostream>
using namespace std;
template <class T1, class T2>
class A
{
T1 v1;
T2 v2;
};
template <class T1, class T2>
class B:public A<T2, T1>
{
T1 v3;
T2 v4;
};
template <class T>
class C:public B<T, T>
{
T v5;
};
int main()
{
/**
* class B<int, double>:public A<double, int>
* {
* int v3;
* double v4;
* };
*
* class A<double, int>
* {
* double v1;
* int v2;
* }
*/
B<int, double> obj1;
/**
* class C<int>:public B<int, int>
* {
* int v5;
* }
*
* class B<int, int>:public A<int, int>
* {
* int v3;
* int v4;
* }
*
* class A<int, int>
* {
* int v1;
* int v2;
* }
*/
C<int> obj2;
return 0;
}
-- 类模板从模板类派生(mubanpaisheng2.cpp)
/**
* 类模板从模板类派生
*
*/
#include <iostream>
using namespace std;
template <class T1, class T2>
class A
{
T1 v1;
T2 v2;
};
template <class T>
class B:public A<int, double> // 此时B从一个模板类A<int, double>里派生出来
{
T v;
};
int main()
{
B<char> obj1; // 自动生成两个模板类: A<int, double>和B<char>
return 0;
}
-- 类模板从普通类派生(mubanpaisheng3.cpp)
/**
* 类模板从普通类派生
*/
#include <iostream>
using namespace std;
class A
{
int v1;
};
template <class T>
class B:public A{ // 所有从B实例化得到的类,都以A为基类
T v;
};
int main()
{
B<char> obj1;
return 0;
}
-- 普通类从模板类派生(mubanpaisheng4.cpp)
/**
* 普通类从模板类派生
*/
#include <iostream>
using namespace std;
template <class T>
class A{
T v1;
int n;
};
class B:public A<int>
{
double v;
};
int main()
{
B obj1;
return 0;
}
2 类模板与友元
-- 函数、类、类的成员函数作为类模板的友元(mubanyouyuan1.cpp)
/**
* 函数、类、类的成员函数作为类模板的友元
*/
#include <iostream>
using namespace std;
void Func1(){}
class A{};
class B
{
public:
void Func(){}
};
template <class T>
class Tmp1
{
friend void Func1();
friend class A;
friend void B::Func();
}; // 任何从Tmp1实例化来的类,都有以上三个友元
int main()
{
}
-- 函数模板作为类模板的友元(mubanyouyuan2.cpp)
/**
* 函数模板作为类模板的友元
* 任意从 template <class T1, class T2>
* ostream& operator<< (ostream& o, const Pair<T1, T2>& p)
* 生成的函数,都是任意Pair模板类的友元
*/
#include <iostream>
using namespace std;
template <class T1, class T2>
class Pair
{
private:
T1 key; // 关键字
T2 value; // 值
public:
Pair(T1 k, T2 v):key(k), value(v){} // 构造函数 使用列表参数进行初始化
// 成员函数 重载小于运算符
bool operator< (const Pair<T1, T2>& p) const;
// 函数模板友元 需要将Pair交给cout进行输出,为了可以吧Pair对象交给cout输出,需要重载左移运算符。但是Pair是一个模板,从Pair可以实例化出来
// 不同类的对象,不同类的对象都要交给cout输出,为每一个不同的类都要去重载一个左移运算符,非常啰嗦。
// 有了吧函数模板作为类模板的友元,就可以解决这个问题
// 函数模板作为类模板的友元
template <class T3, class T4> // 为了将Pair对象交给cout输出 重载左移运算符
friend ostream& operator<< (ostream& o, const Pair<T3, T4>& p);
};
template <class T1, class T2>
bool Pair<T1, T2>::operator<(const Pair<T1, T2> &p) const {
//“小”的意思就是关键字小
return key < p.key;
}
template <class T1, class T2>
ostream& operator<< (ostream& o, const Pair<T1, T2>&p)
{
o << "(" << p.key << "," << p.value << ")";
return o;
}
int main()
{
Pair<string, int> student("Tom", 29);
Pair<int, double> obj(12, 3.14);
cout << student << " " << obj;
return 0;
}
-- 函数模板作为类的友元(mubanyouyuan3.cpp)
/**
* 函数模板作为类的友元
* 所有从
* template <class T>
* void Print(const T& p)生成的函数,都成为A的友元
* 但是自己写的函数
* void Print(int a){}不会成为A的友元
*/
#include <iostream>
using namespace std;
class A
{
int v;
public:
A(int n):v(n){} // 构造函数 使用列表参数初始化
// 函数模板作为类的友元
template <class T>
friend void Print(const T& p);
};
template <class T>
void Print(const T& p)
{
cout << p.v;
}
int main()
{
A a(4);
Print(a);
return 0;
}
-- 类模板作为类模板的友元(mubanyouyuan4.cpp)
/**
* 类模板作为类模板的友元
* A<double>类,成了B<int>类的友元。任何从A模板实例化出来的类,都是任何B实例化出来的类的友元
*/
#include <iostream>
using namespace std;
template <class T>
class B
{
T v;
public:
B(T n):v(n){}
template <class T2>
friend class A;
};
template <class T>
class A
{
public:
void Func()
{
B<int> o(10);
cout << o.v << endl;
}
};
int main()
{
A<double> a;
a.Func();
return 0;
}
3 类模板与静态成员变量的关系
-- 类模板中可以定义静态成员,那么从该类模板实例化得到的所有类,都包含同样的静态成员
-- eg(templateAndStatic.cpp)
/**
* 类模板和static成员
* 从类A中实例化出来的所有的类中都会有static int count这个静态成员,不同类的count静态成员放在内存的不同位置
* 在写静态成员变量的时候,静态成员必须拿到类的外面单独声明, 从包含静态成员类模板实例化出来一个类,同样需要吧这个类的静态成员拿到外面进行声明
*/
#include <iostream>
using namespace std;
template <class T>
class A
{
private:
static int count;
public:
A()
{
count ++;
}
~A()
{
count --;
}
A(A&)
{
count ++;
}
static void PrintCount()
{
cout << count << endl;
}
};
template<> int A<int>::count = 0; // 第一个int代表静态成员变量的类型
template<> int A <double>::count = 0;
int main()
{
A<int> ia;
A<double> da;
ia.PrintCount();
da.PrintCount();
return 0;
}
-- 在写静态成员变量的时候,静态成员必须拿到类的外面单独声明, 从包含静态成员类模板实例化出来一个类,同样需要吧这个类的静态成员拿到外面进行声明