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

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

C++11及BOOST特性之三类成员的初始化和类似foreach的”糖块语法”  

2013-12-17 11:19:49|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

C++11BOOST特性之三类成员的初始化和类似foreach糖块语法

 

昨天在VS2013上写程序,因为是做一个其它程序的小测试,所以随手就把一个类的成员在声明的时候初始化了。也知道是错的,但是又暂时用不到它,所以就过了下,才回过头来看它,结果发现这个下面竟然没有智能提示有错误。

这个可奇怪了,VS2013的智能感知做得相当不错,忽然好像想起在C++11中,类成员变量可以直接初始化了。然后就写一段一样的程序放到VS2010,结果就报错了。

查了下资料,果然是,在C++11中,如下代码是正确的:

class StdWiat

{

public:

         StdWiat ();

         ~StdWiat ();

public:

         void NoticeOne();

         void NoticeAll();

 

private:

            bool _flag = false;        //错误

        static const int _sci = 7;   // 正确

        const int _ci = 7;    // 错误:无static

        static int s_i = 7;              // 错误:无const

        static const int s_ci = var;  // 错误:初始化值不是常量表达式

        static const string s_cs = odd; //错误:非整型

};

红色部分在不支持C++11的编译器上,会报错误,说不是静态和常量的不能初始化。那么这么做有什么好处呢?在C++11中,下面代码

class StdWiat

{

public:

         StdWiat ();

         ~StdWiat ();

public:

         void NoticeOne();

         void NoticeAll();

 

private:

            bool _flag = false;        //在非C++11支持的编译器上错误

};

它等同于:

class StdWiat

{

public:

         StdWiat ():_flag(false){};

         ~StdWiat ();

public:

         void NoticeOne();

         void NoticeAll();

 

private:

            bool _flag ;

 

};

这就不得不谈到在C++11上支持的委托构造(即类的构造函数可以调用自己另外的构造函数)。举个简单的例子,如果一个类有N个构造函数:

class StdWiat

{

public:

         StdWait ():StdWait(7){};//这里调用自己的另外一个构造函数

         StdWait(int var):_tag(var){};

         ~StdWait ();

public:

         void NoticeOne();

         void NoticeAll();

 

private:

            bool _flag ;

        int _tag;

};

另外还有一种是父子类时,C++11允许继承父类的构造函数,在原来的C++中,大家都知道一般把析构函数写成virtual,而不能把构造函数写成virtual,而且构造函数即使子类可以完全使用父类的也没法用,只能重复的写一个。这就造成了一些生重复的代码,而在C#JAVA等语言中,已经可以调用自己的父类构造函数。

Class Base

{

Public:

         Base(int tag);

~Base();

};

class StdWiat :Base

{

public:

         StdWiat ();

explicit StdWiat (int tag) : _tag(tag) {}//说明:using BaseClass::BaseClass;

         ~StdWiat ();

public:

         void NoticeOne();

         void NoticeAll();

 

private:

            bool _flag = false;  

            int _tag;    

};

注意:这个例子可以通过给new_number设定一个默认参数来达到相同的效果.但是,这种新语法可以让这个默认值在实现中来设置而不是在接口中设置.这带来的一个好处就是,对库代码的维护者而言,在接口中(头文件中)声明默认值,这个默认值被嵌入到了调用端;要改变这个默认值的话,调用端的代码都需要重新编译.委托构造可以在实现中(CPP文件中)来改变这个默认值, 这样调用端的代码就不需要重新编译,只用重新编译这个库就可以了.

    还有一个附加说明: C++03认为,构造函数执行完了一个对象就被构造好了. C++11则认为,只要任何一个构造函数执行完了,对象就算构造完成了. 由于可能有多构造函数会被执行,C++11的这种做法就意味着,所有的委托构造函数都将在一个已经用它自己类型完全构造好的对象上执行.这句话什么意思呢?举个例子, B 继承自 A, B的构造函数里调用了A的构造函数;A的构造函数执行完以后,就已经有一个A类的对象构造完成了.而这时B的构造函数不会再构造一个新对象,而是把那个A对象改造成B类的对象(这是我的推测).再举一个例子,C有两个构造函数C1C2, C2调用了C1. C1执行完后,已构造好了一个C类对象.而这时C2的代码会直接作用在这个对象上,不会再构造一个新对象.C++03就会构造2个对象,其中一个是临时对象.

    对于基类的构造函数,C++11允许一个类指定要不要继承基类的构造函数.注意,这是一个"全部""全不"的特性,要么继承基类的全部构造函数,要么一个都不继承.

上面的说明是从别人那儿转来的。

当然,除了上面的,还是有其它一些好处,比如在类构造函数中,有N个重载的构造函数中,其它每个构造函数都得初始化好多变量,这些变量都是一样的。那么有两种解决方法,一种就是每次都初始化一次,另外就是写一个公共的函数,让所有的构造函数来调用。但是如果有了C++11中的方法就简单了,直接赋值就可以了。

说完了初始化,再说一下糖块语法,大家都知道在原来遍历泛型集合,比如list时:

For(std::list:: iterator it=mylist.begin();it!=mylist.end();it++){}

然后在C++11中可以:for(type &t:mylist ){}

是不是类似于foreach。很好吧。这个在C++11中叫做“基于范围的for循环”

好好学习吧。

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

历史上的今天

评论

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

页脚

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