设为首页 加入收藏

TOP

c++11深入学习(一)
2015-07-20 17:19:29 来源: 作者: 【 】 浏览:8
Tags:深入 学习

委托构造函数

在引入C++ 11之前,如果某个类有多个重载的构造函数,且这些构造函数中有一些共同的初始化逻辑,通常都需要再编写一个带参数的初始化函数,然后在这些构造函数中调用这个初始化函数。在C++ 11中,再也不用这么麻烦了。我们可以实现一个最基础的构造函数,其他构造函数都调用这个构造函数。示例代码如下:

?

?

?

?

1 class CPerson

2 {

3 public:

4 CPerson() : CPerson(0, ) { NULL; }

5 CPerson(int nAge) : CPerson(nAge, ) { NULL; }

6 CPerson(int nAge, const string &strName)

7 {

8 stringstream ss;

9 ss << strName << is << nAge << years old.;

10 m_strInfo = ss.str();

11 }

12

13 private:

14 string m_strInfo;

15 };

?

?

统一的初始化语法

在引入C++ 11之前,有各种不同的初始化语法。在C++ 11中,仍可以使用这些初始化语法,但也可以选择使用新引入的统一的初始化语法。统一的初始化语法用一对大括号{}表示,使用{}初始化语法还可有效地避免窄转换。示例代码如下:

?

?

?

?

1 int a{5};

2 char c{'X'};

3 int p[5] = {1, 2,3, 4, 5};

4 vector vctTemp{1, 2, 3};

5 CPerson person{10, Mike};

6 int b = 5.3; // b赋值成5,发生了窄转换

7 int d{5.3}; // 会提示编译错误,避免了窄转换

?

?

语法甜点4:nullptr

nullptr是C++ 11中新加的一个关键字,用于标识空指针。引入nullptr后,可以解决某些函数重载时的二义性问题。示例代码如下:

?

1 void F(int a)

2 {

3 cout << a << endl;

4 }

5

6 void F(char *p)

7 {

8 assert(p != NULL);

9

10 cout << p << endl;

11 }

12

13 int main(int argc, _TCHAR* argv[])

14 {

15 int *p = nullptr;

16 int *q = NULL;

17 bool bEqual = (p == q); // 两个指针值是相等的,bEqual为true

18 int a = nullptr; // 编译失败,nullptr不是转换为int

19

20 F(0); // 在C++ 98中编译失败,有二义性;在C++ 11中调用F(int)

21 F(nullptr); // 调用F(char *)

22

23 getchar();

24 return 0;

25 }

?

?

成员变量初始化

与Java和C#中的用法一样,可以对成员变量进行就地初始化。示例代码如下:

?

?

1 class CPerson

2 {

3 private:

4 int m_nAge = 10;

5 string m_strName = Mike;

6 };

?

?

默认或禁用函数

当我们定义了自己的带参数的构造函数时,编译器将不再生成默认的构造函数,如果此时想使用默认的构造函数,则必须显式地声明并定义不带参数的构造函数。在C++ 11中,我们可以使用default关键字来表明我们希望使用默认的构造函数。类似的,当我们不想外部使用编译器自动生成的构造函数或赋值函数时,我们一般需要将其声明成protected或private的。在C++ 11中,我们可以使用delete关键字来表明我们不希望编译器生成默认的构造函数或赋值函数。示例代码如下:

?

?

1 class CPerson

2 {

3 public:

4 CPerson() = default;

5 CPerson(const CPerson &person) = delete;

6 };

?

?

static_assert

静态断言static_assert由一个常量表达式和一个字符串构成。在编译期间,将计算常量表达式的值,如果为false,字符串将作为错误信息输出。示例代码如下:

?

?

1 char a = 10;

2 static_assert(sizeof(a)==4, a is not an integer.);

?

?

模板右边双括号

在C++ 98中,vector > vctTemp是一个非法的表达式,编译器会认为右边的>>是一个移位操作符,因此必须修改为vector > vctTemp,即在右边的两个>中间添加一个空格。在C++ 11中,这将不再是一个问题,编译器将能够识别出右边的双括号是两个模板参数列表的结

-

?

继承的构造函数

当一个派生类的某个函数隐藏了基类中的某个同名函数时,如果我们想在派生类中导出基类中的这个同名函数,可以通过using Base::Func的方式将基类中的这个同名函数引入到派生类的作用域内。当该方法只对普通成员函数有效,不能用于构造函数。在C++ 11中,如果派生类认为基类的构造函数已经足够,则也可以使用using Base::Base的方式将基类的构造函数引入到派生类的作用域内。但需要注意的是,此时派生类中的成员变量并没有进行初始化,所以应当对这些成员变量进行就地初始化。示例代码如下:

?

?

?

?

1 class CBase

2 {

3 };

4

5 class CDerived : public CBase

6 {

7 public:

8 using CBase::CBase;

9 CDerived(int nData) : m_nData(nData) { NULL; }

10

11 private:

12 int m_nData = 10;

13 };

?

?

初始化列表

在引入C++ 11之前,只有数组能使用初始化列表。在C++ 11中,vector、list等各种容器以及string都可以使用初始化列表了。初始化列表对应的类为initializer_list,vector、list等各种容器以及string之所以可以使用初始化列表,是因为它们重载了参数类型为initializer_list的构造函数(称为初始化列表构造函数)和赋值函数(称为初始化列表赋值函数)。下面是一些使用初始化列表的例子。

?

?

?

?

1 void Print(const initializer_list &ilData)

2 {

3 for (auto a : ilData)

4 {

5 cout << a << endl;

6 }

7 }

8

9 int main(int argc, _TCHAR* argv[])

10 {

11 vector vctNum = {1, 2, 3, 4, 5};

12 map mapID2Name = {{92001, Jack}, {92002, Mike}};

13 string strText{hello world};

14 Print({});

15 Print({1, 2});

16 Print({1, 2, 3, 4, 5});

17

18 getchar();

19 return 0;

20 }

?

?

?

非成员的begin和end

在C++ 03中,标准容器都提供了begin和end成员函数,但对于普通数组,则只能使用不同的写法。比如:

?

?

1 vector v;

2 int a[100];

3 sort(v.begin(), v.end());

4 sort(a, a+sizeof(a)/sizeof(a[0]));

为了统一语法,C++ 11提供了

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Leetcode_Longest Common Prefix 下一篇Leetcode_Palindrome Number

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何理解c语言指针和 (2025-12-27 01:19:11)
·为什么C标准库没有链 (2025-12-27 01:19:08)
·玩转C语言和数据结构 (2025-12-27 01:19:05)
·MySQL 基础入门视频 (2025-12-26 23:20:22)
·小白入门:MySQL超详 (2025-12-26 23:20:19)