在同一个模板的不同实例化之间没有继承关系(也不存在隐式转换关系);为什么呢?
以继承关系为例,当编译器遇到“派生类模板<T>”的定义时,它知道它继承于"基类模板<T>",但是T是一个模板参数,这个直到更迟一些才能被确定当"派生类模板<T>"被实例化的时候。不知道T是什么,就没有办法知道“基类<T>” 是什么样子的。
为了使具有继承关系(隐式转换关系)的类进行转换,必须在拷贝构造函数或赋值函数中使用“成员函数模板”。
为了避免不具备转换关系的类型进行转换,通过成员初始化列表,用 cEmpty<U> 持有的类型为 U* 的指针初始化 cEmpty<T> 的类型为 T* 的数据成员。这只有在“存在一个从一个 U* 指针到一个 T* 指针的隐式转换”的条件下才能编译。最终的效果就是 cEmpty<T> 现在有一个泛型化拷贝构造函数,它只有在传入一个"兼容类型"的参数时才能编译。
成员函数模板是一个极好的东西,它们不会改变语言的基本规则。在一个类中声明一个泛型化拷贝构造函数(一个成员模板)不会阻止编译器生成它们自己的拷贝构造函数(非模板的),所以如果要全面支持拷贝构造,必须既声明一个泛型化拷贝构造函数又声明一个“常规”拷贝构造函数。这同样适用于赋值函数。
以继承关系为例,当编译器遇到“派生类模板<T>”的定义时,它知道它继承于"基类模板<T>",但是T是一个模板参数,这个直到更迟一些才能被确定当"派生类模板<T>"被实例化的时候。不知道T是什么,就没有办法知道“基类<T>” 是什么样子的。
为了使具有继承关系(隐式转换关系)的类进行转换,必须在拷贝构造函数或赋值函数中使用“成员函数模板”。
为了避免不具备转换关系的类型进行转换,通过成员初始化列表,用 cEmpty<U> 持有的类型为 U* 的指针初始化 cEmpty<T> 的类型为 T* 的数据成员。这只有在“存在一个从一个 U* 指针到一个 T* 指针的隐式转换”的条件下才能编译。最终的效果就是 cEmpty<T> 现在有一个泛型化拷贝构造函数,它只有在传入一个"兼容类型"的参数时才能编译。
成员函数模板是一个极好的东西,它们不会改变语言的基本规则。在一个类中声明一个泛型化拷贝构造函数(一个成员模板)不会阻止编译器生成它们自己的拷贝构造函数(非模板的),所以如果要全面支持拷贝构造,必须既声明一个泛型化拷贝构造函数又声明一个“常规”拷贝构造函数。这同样适用于赋值函数。
详见代码吧!
#include <iostream>
using namespace std;
template<typename T>
class cEmpty
{
public:
cEmpty() // 缺省构造函数
{
cout<<"default constructor"<<endl;
}
cEmpty(T data) // 带参构造函数
{
cout<<"constructor variable ="<<data<<endl;
}
cEmpty( const cEmpty& ) // 拷贝构造函数
{
cout<<"copy constructor"<<endl;
}
//通过成员初始化列表,用 cEmpty<U> 持有的类型为 U* 的指针初始化 cEmpty<T> 的类型为 T* 的数据成员。
//这只有在“存在一个从一个 U* 指针到一个 T* 指针的隐式转换”的条件下才能编译。
//最终的效果就是 cEmpty<T> 现在有一个泛型化拷贝构造函数,它只有在传入一个"兼容类型"的参数时才能编译。
//只有在other.get()能够隐式转换为heldPtr时,才能编译通过。
template<typename U>
cEmpty( const cEmpty<U>& other):heldPtr(other.get()) // 模板拷贝构造函数
{
cout<<"template member copy constructor"<<endl;
}
T* get() const
{
return heldPtr;
}
cEmpty& operator=( const cEmpty& ) // 赋值运算符
{
cout<<"assignment constructor"<<endl;
}
template<typename U>
cEmpty& operator=( const cEmpty<U>& ) // 模板赋值运算符
{
cout<<"template member assignment constructor"<<endl;
}
~cEmpty() // 析构函数
{
cout<<"destructor"<<endl;
}
private:
T *heldPtr;
};
class Base
{
};
//必须是继承关系,否则不能进行隐式转换
class Derived:public Base
{
};
int main()
{
cEmpty<Derived> derived;
cEmpty<Base> base(derived);
return 1;
}