注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

暇隙读书(7)——模板中的技巧性基础知识---C++Templates  

2013-05-23 21:57:17|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

暇隙读书(7)——模板中的技巧性基础知识---C++Templates

在模板中,有很多与C++的语法看上去不一样的用法,初次接触者可能会觉得很不可思议,但编译却又可以通过。好,那就让大家看一看几个常用的技巧性的东西。

一、typename关键字:这个关键字都知道是可以和class关键字在模板的定义中进行互换的。但在下面这种情况:

template<typename T>

class MyClass

{

    Typename T::SubType*ptr;

    …

};

上面的程序中,第二个typename被用来说明:SubType是定义于类T内部的一种类型,因此,ptr是一个指向T::SubType类型的指针。否则的话,它就会被认为是一个类的内部的静态成员,那么typename T::SubType*ptr就会被看作是类T的静态成员SubTypeptr的乘积。

同样,看下面的用法:

Template<int N>

Void printBitset (std::bitset<N> const& bs)

{

    Std::cout<<bs.template to_string<char,char_traits<char>,allocator<char> >();

}

注意bs.template这个构造,如果不有使用它,编译器将不知道bt.template后面的小于(<)并不是数学中的小于号,而模板参数实参列表的起始符号。也就是说,只有在编辑器判断小于号之前,存在依赖于模板参数的构造,才会出现这样的问题,在这个例子中,传入参数bs就是依赖于模板参数N的构造。

二、使用this->

大家都知道,对于类来说,都存在一个指向自己的this指针,访问自己或者从父类中的成员时候可以直接使用this->xxx来使用,同样,如果你不写它,那么默认和this指针是一样的;但这个方式在模板中千万要引起注意。举个如下的例子:

Template<typename T>

Class Base

{

    Public:

    Void exit();

};

 

Template<typename T>

Class Derived:Base<T>

{

    Public:

        Void foo()

        {

            Exit();

}

};

红色的函数调用可不是调用的父类中的exit()函数,或者是一个错误,或者是另外一个其它的哪儿的同名的函数。

如果想使用基类中的声明,并且依赖于模板参数的符号(函数或者变量),你应该在它们前面使用this->或者Base<T>::

三、成员模板

这个就比较简单了,只是改变大家的一个思维方式罢了。

Template<typename T>

Class Stack

{

 Private:

    Std::deque<T> elems;

    …

};

它得应用那就非常广泛了,如果大家经常写一些应用层面上的代码就会发现这个非常有用。

四、模板的模板参数

这个也比较好理解,看下面的例子:

Template <typename T,

Template<typename ELEM> class CONT = std::deque>

Class Stack

{

    Private:

        CONT<T> elems;

};

你可以这样使用:

Stack<int,std::vector<int> > vStack;

如果你借助于模板的模板参数还可以只指定容器的类型而不指定所含元素的类型。

Stack<int,std::vector> vStack;

五、零初始化和使用字符串做为函数模板的实参

大家都知道一般在基本类型中,会有一个不确定的值来给他一个初值,如果你没有给其赋值的情况下。但有的时候模板却需要有一个初始的零值 。那怎么办呢?很简单:

Template <typename T>

Void foo()

{

    T x = T();

}

而对于类模板:

Template <typename T>

Class MyClass

{

    Private:

        T x;

    Public:

        MyClass():x(){//确认X已被初始化,内建类型对象也是如此}

}

另外一个就是字符串做模板的实参了,大家都知道,字符串做为参数其实是传递一个指针,而不同的字符串肯定有不同的长度,而且在不同的情况下,比如std::stringchar*的比较,都可能错误,这个没有通用的解决办法,你可以如下方式来解决之。

1、是使用非引用参数来取代引用参数;

2、是进行重载,编写接收引用参数和非引用参数的两个重载函数。不过个可能会引起二义性。

3、对具体的类型进行重载如上面说的std::string

4、重载数组类型

5、强制要求应用程序的程序员显式进行类型转换。

最近又有些忙,忙里偷闲,也要看看书。

积少成多。

  评论这张
 
阅读(546)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017