在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1. typename template <typename T> class MyClass {
typename T::SubType * ptr;
… }; 如果不使用typename,SubType会被认为是一个静态成员,T::SubType就会被解释成两个变量的乘积。 typename的典型应用: STL容器的iterator // basics/printcoll.hpp
#include <iostream>
// print elements of an STL container
template <typename T> void printcoll (T const& coll) { typename T::const_iterator pos; // iterator to iterate over coll typename T::const_iterator end(coll.end()); // end position for (pos=coll.begin(); pos!=end; ++pos) {
std::cout << *pos << ' ';
} std::cout << std::endl; } class stlcontainer {
… typedef … iterator; // iterator for read/write access typedef … const_iterator; // iterator for read access … };
2. this-> 下面的例子中foo()调用exit(),它不会调用父类Base的exit(),而是会调用外部定义的exit()。如果要调用父类的exit()就需要加上this->或者Base<T>:: template <typename T> class Base {
public:
void exit();
}; template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // calls external exit() or error
} };
3. 成员模板(Member Templates) 我们有这样的需求:把两个不同模板类型的类相互赋值。 Stack<int> intStack1, intStack2; // stacks for ints Stack<float> floatStack; // stack for floats … intStack1 = intStack2; // OK: stacks have same type
floatStack = intStack1; // ERROR: stacks have different types
这里我们就需要使用成员模板 // basics/stack5decl.hpp
template <typename T> class Stack {
private:
std::deque<T> elems; // elements
public:
void push(T const&); // push element void pop(); // pop element T top() const; // return top element bool empty() const { // return whether the stack is empty return elems.empty();
} // assign stack of elements of type T2
template <typename T2> Stack<T>& operator= (Stack<T2> const&); }; operator=的实现: // basics/stack5assign.hpp
template <typename T> template <typename T2> Stack<T>& Stack<T>::operator= (Stack<T2> const& op2) { if ((void*)this == (void*)&op2) { // assignment to itself? return *this; } Stack<T2> tmp(op2); // create a copy of the assigned stack
elems.clear(); // remove existing elements
while (!tmp.empty()) { // copy all elements elems.push_front(tmp.top()); tmp.pop(); } return *this; }
4. 模板的模板参数(Template Template Parameters) 当我们要指定一个Stack模板类型时,要这样写: Stack<int,std::vector<int> > vStack; // integer stack that uses a vector 这样有些繁琐int出现了两次,我们希望的是: Stack<int,std::vector> vStack; // integer stack that uses a vector 此时就要用到模板的模板参数 // basics/stack7decl.hpp
template <typename T, template <typename ELEM> class CONT = std::deque > class Stack {
private:
CONT<T> elems; // elements
public:
void push(T const&); // push element void pop(); // pop element T top() const; // return top element bool empty() const { // return whether the stack is empty return elems.empty();
} }; 这里有几点需要注意的是: 1)template <typename ELEM> class CONT = std::deque中的class不能换成typename 2)模板的模板参数不能用于函数模板 3)根据上述的默认值std::deque会得到一个编译错误: error C3201: the template parameter list for class template 'std::deque' does not match the template parameter list for template parameter 'CONT' 发生这个错误的原因是: std::deque除了ELEM这个模板参数之外,还有另一个allocator的参数:typename ALLOC = std::allocator<ELEM> 在模板编译的时候要求模板定义的参数CONT与模板的实参完全一致,我们需要将allocator参数加上: template <typename T, template <typename ELEM, typename ALLOC = std::allocator<ELEM> >
class CONT = std::deque>
class Stack {
private:
CONT<T> elems; // elements
… };
5. 初始化为0(Zero Initialization) 这里要解决的问题是如何将模板类型的变量初始化 template <typename T> void foo()
{ T x = T(); // x is zero (or false)ifT is a built-in type
} template <typename T> class MyClass {
private:
T x; public:
MyClass() : x() { // ensures that x is initialized even for built-in types
} … }; 上面分别介绍了对函数内的局部变量和类变量的初始化。
6. 字符串作为函数模板的实参 // basics/max5.cpp
#include <string>
// note: reference parameters
template <typename T> inline T const& max (T const& a, T const& b) { return a < b ? b : a;
} int main()
{ std::string s; ::max("apple","peach"); // OK: same type ::max("apple","tomato"); // ERROR: different types ::max("apple",s); // ERROR: different types } 这里发生编译错误的原因是"apple”和"tomato”的类型分别是char const[6]和char const[7]。 最好的解决方法就是为字符串重载max()
7. 模板源代码组织 (1)包含模型 把模板函数和模板类的实现放在头文件中,这个方法是相对来说最简单,最推荐的方法。 (2)显式实例化 手工对需要的模板类型进行实例化,而不依赖编译器。这种做法的好处就是可以把模板函数的声明和定义分开,并且可以精确控制模板实例的准确位置,坏处就是需要人工的跟踪每个需要实例化的实体,不适合用于大项目。
包含模型和显式实例化整合
(3) 分离模型 分离模型就是通过使用export关键字来实现模板声明和定义的分离,很完美?不过它有一个非常重大的缺陷: 它会产生看不见的代码耦合(模板的声明和定义在不同文件中),当定义发生变化时,所有调用该模板函数的地方都需要重编译,而这些对一些编译工具来说是不可见的,比如Makefile。所以不推荐使用。
分离和包含模型的转换 // basics/myfirst4.hpp
#ifndef MYFIRST_HPP
#define MYFIRST_HPP
// use export if USE_EXPORT is defined
#if defined(USE_EXPORT)
#define EXPORT export #else
#define EXPORT
#endif
// declaration of template
EXPORT 全部评论
专题导读
上一篇:MVC开发中的常见错误-01未能加载文件或程序集“EntityFramework,Version=6.0.0.0,Cult ...发布时间:2022-07-13下一篇:C#图像处理:截图程序(包含鼠标)发布时间:2022-07-13热门推荐
热门话题
阅读排行榜
|
请发表评论