目录
前面我们说到的类模板是在一个类中,分类内实现,类外实现和分文件写几种情况。继承是类的重要特性,所以我们需要考虑下在继承下,类模板的使用情况。
在继承中,类模板也分为三种情况。
1. 父类是类模板,子类不是类模板。
// 父类 -- 是类模板
template <typename T>
class A {
public:
A(int a);
T getA()const;
private:
T a;
};
template <typename T>
A<T>::A(int a) {
this->a = a;
}
template <typename T>
T A<T>::getA()const {
return a;
}
// 子类 -- 是普通的类
class B :public A<int> {
public:
B(int a, int b);
int getB()const;
private:
int b;
};
/*
继承父类,在子类的构造函数处调用父类的构造函数,使用父类的构造函数,初始化继承来的
属性,因为此处只调用了父类的构造函数,所以需要在调用父类构造函数时用<>传入类型参数
当然在调用父类的时候,我们可以传入具体的类型参数。
*/
B::B(int a, int b):A<int>(a){
this->b = b;
}
int B::getB()const {
return b;
}
int main(void) {
A<int> a(100);
B b(100,10);
cout << a.getA() << endl;
cout << b.getA() << endl;
cout << b.getB() << endl;
system("pause");
return 0;
}
代码分析:
1. 上面的代码中,父类A是一个类模板,子类B是一个普通类。
2. 子类继承,我们在:之后写上继承的父类,但是如果父类是类模板的话我们需要使用<>传入类型,来实例化父类中类型参数。 class B :public A<int> {};因为子类是普通类型,所以此处传入的是具体的类型。
3. 在继承时,使用<>传入类型参数之后,后面就可以直接使用具体的类型了而且可以不再使用<>传入类型参数。
B::B(int a, int b):A<int>(a){ this->b = b;} ,比如此处的<int>可以不写
总结:
1. 如果父类为类模板,子类为普通类。那么在继承的时候,需要使用<>传入类型来实例化类型参数。
2. 前面实例化之后,后面就可写可不写了。
2. 父类是普通类,子类是类模板。
// 父类 -- 是普通的类
class A {
public:
A(int a);
int getA()const;
private:
int a;
};
A::A(int a) {
this->a = a;
}
int A::getA()const {
return a;
}
// 子类 -- 是类模板
template <typename T>
class B :public A {
public:
B(int a, T b);
T getB()const;
private:
T b;
};
template <typename T>
B<T>::B(int a, T b) :A(a) {
this->b = b;
}
template <typename T>
T B<T>::getB()const {
return b;
}
int main(void) {
A a(100);
B<int> b(100, 10);
cout << a.getA() << endl;
cout << b.getA() << endl;
cout << b.getB() << endl;
system("pause");
return 0;
}
代码分析:
1. 上面看在子类为类模板,父类为普通类的情况下。 和普通的继承是一样的。
2. 对于子类,那就是模板的使用方式了。
3. 父类和子类都是类模板
就是将上面的两种结合起来,其实也是类似的。
4. 总结
1. 子类从模板类继承的时候,需要让编译器知道父类的数据类型具体是什么。 (可以写具体的类型,也可以写子类定义的虚拟类型)
2. 一个类模板可以作为基类,派生出派生模板类。