C++11 委派构造函数特性怎么使用?

在代码开发中,C语言和C++都是基础语言,是很多web开发人员的入门级必学语言。但在C++98 中,类成员构造问题还存在一些问题,为此C++11提出了一些新特性。

C++98中如果一个类有多个构造函数且要实现类成员构造,这些构造函数通常要包含基本相同的类成员构造代码。在最坏的情况下,相同的类成员构造语句被拷贝粘贴在每一个构造函数中。

基于C++98中的类成员构造问题,C++11新特性中,程序员可以将公有的类成员构造代码集中在某一个构造函数里,这个函数被称为目标构造函数。其他构造函数通过调用目标构造函数来实现类成员构造,这些构造函数被称为委派构造函数。在该新特性提出之前,构造函数是不能显式被调用的,委派构造函数打破了这一限制。下面小编将和大家一起来看看C++11委派构造函数的使用方法。

1、委派构造函数的使用

为了详细了解C++11的新特性,我们可以通过下面这个例子来看看具体是怎么使用的:

程序源代码 (delegatingctor1.cpp)

class A{

public:

// A(int i)为 A()的委派构造函数

A(): A(0){}

// A(int i, intj)为 A(int i)的委派构造函数

A(int i): A(i,0){}

// 委派构造链为 A()->A(int i)->A(int i, int j)

A(int i, int j){

num1=i;

num2=j;

average=(num1+num2)/2;

}

private:

int num1;

int num2;

int average;

};

从上面这个例子中,可以看出,在构造函数 A()的初始化列表里,程序调用了A(0), 这就是委派构造函数的语法。 我们称 A(int i)为 A()的目标构造函数,而 A()为 A(int i)的委派构造函数。同理,A(int i, int j)为 A(int i)的目标构造函数,而 A(int i) 为 A(int i, int j)的委派构造函数。在利用了委派构造函数后,整个程序变得更加的清楚和简洁。目标构造函数和委派构造函数跟其他普通的构造函数一样有相同的接口和语法,它们并没有特殊的处理和标签。通过这个例子,我们也可以看出C++11中一个委派构造函数可以是另一个委派构造函数的目标构造函数,委派构造函数和目标构造函数是相对而言的。目标构造函数是通过重载和类参数推导准则而选定的。

在C++函数委派过程中,当目标构造函数函数执行完毕后,委派构造函数继续执行它自己函数体内的其他语句。可以通过下面这个例子的方式实现:

程序源代码 (delegatingctor2.cpp)

#include<iostream>

using namespacestd;

class A{

public:

A(): A(0){ cout << "In A()"<< endl;}

A(int i): A(i,0){cout << "In A(int i)" << endl;}

A(int i, int j){

num1=i;

num2=j;

average=(num1+num2)/2;

cout <<"In A(int i, int j)" << endl;

}

private:

int num1;

int num2;

int average;

};

int main(){

A a;

return 0;

}

该例子的输出为:

In A(int i, intj)

In A(int i)

In A()

2、委派构造函数的异常处理

当目标构造函数抛出异常时,该异常会被委派构造函数中的 try 模块抓取到。并且在这种情况下,委派构造函数自己函数体内的代码就不会被执行了。

下面我们也通过例子来看看,构造函数A(int i, int j)抛出一个异常,该异常依次被委派构造函数 A(int i)和 A()抓取到,且 A(int i)和 A()的函数体没有被执行。

程序源代码 (exception1.cpp)

#include<iostream>

using namespacestd;

class A{

public:

A();

A(int i);

A(int i, int j);

private:

int num1;

int num2;

int average;

};

A:: A()try: A(0){

// A()函数体不会被执行到

cout <<"A() body"<< endl;

}

catch(...) {

cout <<"A() catch"<< endl;

}

A::A(int i) try: A(i, 0){

// A(int i)函数体不会被执行到

cout <<"A(int i) body"<< endl;

}

catch(...) {

cout <<"A(int i) catch"<< endl;

}

A::A(int i, intj) try {

num1=i;

num2=j;

average=(num1+num2)/2;

cout <<"A(int i, int j) body"<< endl;

// 抛出异常

throw 1;

}

catch(...) {

cout <<"A(int i, int j) catch"<< endl;

}

int main(){

try{

A a;

cout <<"main body"<< endl;

}

catch(...){

cout <<"main catch"<< endl;

}

return 0;

}

该例的输出为:

A(int i, int j)body

A(int i, int j)catch

A(int i) catch

A() catch

main catch

当委派构造函数抛出异常时,系统会自动调用目标构造函数内已经构造完成的对象的析构函数。在下面的例子中,目标构造函数 A(int i, int j)完成了对象 a 的构造。它的委派构造函数 A(inti)在执行时抛出了一个异常,此时对象 a马上被析构,且 A(int i)的委派构造函数 A()的函数体不再被编译器执行,这和上例中所描述的原则是一致的。

程序源代码 (exception2.cpp)

#include<iostream>

using namespacestd;

class A{

public:

A();

A(int i);

A(int i, int j);

~A();

private:

int num1;

int num2;

int average;

};

A::A(): A(0){

// A()函数体不会被执行到

cout <<"A()body" << endl;

}

A::A(int i) try: A(i, 0){

cout <<"A(int i) body"<< endl;

// 抛出异常,对象 a 将被析构

throw 1;

}

catch(...) {

cout <<"A(int i) catch"<< endl;

}

A::A(int i, intj){

num1=i;

num2=j;

average=(num1+num2)/2;

cout <<"A(int i, int j) body"<< endl;

}

A::~A(){

cout <<"~A() body"<< endl;

}

int main(){

A a;

return 0;

}

该例的输出为:

A(int i, int j)body

A(int i) body

~A() body

A(int i) catch

3、委派构造函数和泛型编程

其实,委派构造函数除了可以使程序员规避构造函数里重复的代码外,还可使构造函数的泛型编程变得更加容易,比如下面这个例子:

程序源代码 (generic.cpp)

#include<iostream>

using namespacestd;

template<typenameT> class A{

public:

A(int i): A(i,0){}

A(double d):A(d, 0.0){}

// 函数模板

A(T i, T j) {

num1=i;

num2=j;

average=(num1+num2)/2;

cout <<"average=" << average << endl;

}

private:

T num1;

T num2;

T average;

};

int main(){

A<int>a_int(1);

A<double>a_double(1.0);

}

该例的输出为:

average=0

average=0.5

上面这段代码中,目标构造函数为函数模板,它在被委派构造函数调用的时候才被实例化,非常方便,无需开发人员再写同类型的目标构造函数。

总结

通过上面的例子,相信大家对C++11委派构造函数具体使用都有了一定的了解和认识。利用C++11 的这个特性可以提高程序的可读性和可维护性,提高开发人员的开发效率。虽然委派构造函数的调用是可能会需要一些系统开销,但是大家还是可以尝试使用。

时间: 2024-10-08 18:46:14

C++11 委派构造函数特性怎么使用?的相关文章

C++11委派构造函数的使用方法

在代码开发中,C语言和C++都是基础语言,是很多web开发人员的入门级必学语言.但在C++98 中,类成员构造问题还存在一些问题,为此C++11提出了一些新特性. C++98中如果一个类有多个构造函数且要实现类成员构造,这些构造函数通常要包含基本相同的类成员构造代码.在最坏的情况下,相同的类成员构造语句被拷贝粘贴在每一个构造函数中. 基于C++98中的类成员构造问题,C++11新特性中,程序员可以将公有的类成员构造代码集中在某一个构造函数里,这个函数被称为目标构造函数.其他构造函数通过调用目标构

C++11初窥二: 继承构造函数和委派构造函数

分析了这两种用法,真想吐槽两句,这两个特性确实有实际需要,但客观来说,现有标准足够用,而且带来的代价也非常大,又给C++复杂的语法糖重重的抹了一笔!!! 一.继承构造函数 继承构造函数的引入原因:如果基类的构造函数很多,那么子类的构造函数想要实现同样多的构造接口,必须一一调用基类的构造函数,有点麻烦 于是乎:C++11引入继承构造函数 class _A { public: _A( int _InInt ) {;} _A( double _InDouble, int _InInt ) {;} _A

C++11模板句柄的实现:委派构造函数、default关键字分析

C++11,使用委派构造函数,并且快速初始化变量,default关键字重声明默认构造函数,回复pod状态.分析与推荐用法. 目前为止,VS2012和2013对异常声明的兼容还是停留在代码沟通的级别,没有进行编译类型检查,出现如下错误可忽略. warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow) 下为:VS2012不支持委托构造函数,建议使用cocos2d-x 3.2及版本的朋友更新VS至2013版. 1>d:\cpp_lab\testque

C++11 标准新特性:Defaulted 和 Deleted 函数

前两天写的铁字中提到了C++的删除函数,今天特地去网上查了查,转载了一篇不错的文章... 转载自 http://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html C++11 标准新特性:Defaulted 和 Deleted 函数 本文将介绍 C++11 标准的两个新特性:defaulted 和 deleted 函数.对于 defaulted 函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代

C++11的一些特性

1.断言是将一个需要为真的表达式放在语句中,在debug模式下检查一些逻辑错误的参数,C++中使用assert需要使用<assert.h>或者<cassert>头文件.有函数定义如下: void fun(int a[],int n) { assert(n>0); //dosomething; } 这样就可以检查n<=0的情况,如果遇到这种情况,程序会调用abort()函数而终止. C++11提供了static_assert断言,它的函数原型接受两个参数,一个是断言表达式

模板句柄实现,委派构造函数的调用,throw声明等

C++11,使用委派构造函数,并且快速初始化变量,default关键字重声明默认构造函数,回复pod状态.分析与推荐用法. 目前为止,VS2012和2013对异常声明的兼容还是停留在代码沟通的级别,没有进行编译类型检查,出现如下错误可忽略. warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow) 下为:VS2012不支持委托构造函数,建议使用cocos2d-x 3.2及版本的朋友更新VS至2013版. 1>d:\cpp_lab\testque

C++11 标准新特性: 右值引用与转移语义

C++ 的新标准 C++11 已经发布一段时间了.本文介绍了新标准中的一个特性,右值引用和转移语义.这个特性能够使代码更加简洁高效. 查看本系列更多内容 | 3 评论: 李 胜利, 高级开发工程师, IBM 2013 年 7 月 10 日 内容 在 IBM Bluemix 云平台上开发并部署您的下一个应用. 开始您的试用 新特性的目的 右值引用 (Rvalue Referene) 是 C++ 新标准 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它实现了转移语义 (Move

[.net 面向对象编程基础] (11) 面向对象三大特性——封装

[.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承.多态. 1.封装概念 封装:每个对象都包含有它能进行操作的所有信息,这个特性称为封装.这样的方法包含在类中,通过类的实例来实现. 2.封装的优点 A.良好的封装能够减少耦合(比如实现界面和逻辑分离) B.可以让类对外接口不变,内部可以实现自由的修改 C.类具有清晰的对外接口,使用者只需调用,无需关心

Qt5 中对 C++11 一些新特性的封装

在 Qt5 中,提供更多 C++11 的特性支持,接下来我们将进行详细的说明. slots (槽) 的 Lambda 表达式 Lambda表达式 是 C++11 中的一个新语法,允许定义匿名函数.匿名函数可用于使用小函数作为参数,而无需显式的进行声明.之前可以通过编写函数指针来达到同样的目的. 在 Qt 4.8 中已经可在一些 QtConcurrent 函数中使用 Lambda 表达式了.但在 Qt5 中甚至可以通过 new connect syntax 来将 Lambda 表达式作为 slot