类模板
- 类模板没有自动类型推导,只能显示调用
template<typename T, typename U>
class Base {};
int main() {
Base<int, double> a; //显示调用
return 0;
}
- 类模板的参数可以有缺省值,而函数模板不可以
template<typename T, typename U = int>
class A {};
- 类模板中的成员函数只有在调用时才会通过模板生成。
// 举例证明
class A {
public:
void func() { cout << "hello world!" << endl; }
};
class B {};
template<typename T>
class C {
public:
void func1() {
data.func();
return ;
}
T data;
};
int main() {
C<A> c1;
c1.func1(); //hello world!
C<B> c2;
//B类中没有func方法。通过模板生成c2对象时12行没有报错,则证明编译期不会直接生成c2对象的func1函数。
// c2.func1(); //但在运行期调用就会报错,这是生成成员函数过程中发现代码12行B中无func方法
return 0;
}
- 在继承场景中,如果父类是类模板,那么子类在继承时需要指定出父类抽象出的数据类型。否则子类也需要是类模板(继续抽象)
template<typename T, typename U>
class Base {};
class A : public Base<int, double> {};
template<typename T, typename U>
class B : public Base<T, U> {};
- 模板类外实现成员函数
template<typename T, typename U>
class A {
public:
void Print(T a, U b);
};
template<typename T, typename U>
void A<T, U>::Print(T a, U b) {
cout << a + b << endl;
return ;
}
- 场景题:实现PrintAny类
// TODO BEGIN
template<typename T>
class PrintAny {
public:
PrintAny(ostream &out) : __out(out) {}
PrintAny& Print(T obj) {
__out << obj;
return *this;
}
PrintAny& endl() {
__out << std::endl;
return *this;
}
private:
ostream &__out; //注意必须是 &
};
// TODO END
int main() {
PrintAny<int> pint(cout);
PrintAny<double> pdouble(cout);
PrintAny<string> pstring(cout);
pint.Print(3).endl(); //3
pdouble.Print(3.3).endl(); //3.3
pstring.Print("hello world").endl(); //hello world
return 0;
}
成员方法模板
// TODO BEGIN
class PrintAny {
public:
PrintAny(ostream &out) : __out(out) {}
template<typename T> //注意
PrintAny& Print(T obj) {
__out << obj;
return *this;
}
PrintAny& endl() {
__out << std::endl;
return *this;
}
private:
ostream &__out;
};
// TODO END
int main() {
PrintAny p(cout);
//此时抽象出的不是类,而是类成员函数的参数
p.Print(3).endl().Print(3.4).endl().Print("hello world").endl();
return 0;
}
/*
3
3.4
hello world
*/