2024年10月explicitc++中的作用(c++中的构造函数加上explicit有什么用)

 更新时间:2024-10-12

  ⑴explicitc++中的作用(c++中的构造函数加上explicit有什么用

  ⑵c++中的构造函数加上explicit有什么用

  ⑶explicit是c++的关键字,意为必须明确的调用构造函数。比如:structb{b(int){}};bb=;//此时是合法的,自动隐式调用b::b(int)构造如果不希望这样,必须明确调用构造函数的话,用explicit关键字。如:structb{explicitb(int){}};bb=;//不合法,编译不通过,不能隐式调用构造函数。bb=b();//合法,必须明确调用了构造函数

  ⑷哥哥姐姐们跪求C++有哪些术语比如英文单词啊标点符号啊谁能告诉我下感激不尽啊

  ⑸按照顺序罗列了一下,可供参考,查阅。.asm(汇编,用法如下:asm(指令字符串);允许在C++程序中嵌入汇编代码。.auto(自动,automatic是存储类型标识符,表明变量“自动”具有本地范围,块范围的变量声明(如for循环体内的变量声明默认为auto存储类型。.bool(布尔类型,C++中的基本数据结构,其值可选为true(真或者false(假。C++中的bool类型可以和int混用,具体来说就是代表false,非代表true。bool类型常用于条件判断和函数返回值。.break(中断、跳出,用在switch语句或者循环语句中。程序遇到break后,即跳过该程序段,继续后面的语句执行。.case用于switch语句中,用于判断不同的条件类型。.catchcatch和try语句一起用于异常处理。.charchar(字符,character类型,C++中的基本数据结构,其值一般为~的int。这个字符对应着个ASCII码。char类型的数据需要用单引号’’括起来。.classclass(类是C++面向对象设计的基础。使用class关键字声明一个类。.constconst(常量的,constant所修饰的对象或变量不能被改变,修饰函数时,该函数不能改变在该函数外面声明的变量也不能调用任何非const函数。在函数的声明与定义时都要加上const,放在函数参数列表的最后一个括号后。在C++中,用const声明一个变量,意味着该变量就是一个带类型的常量,可以代替#define,且比#define多一个类型信息,且它执行内链接,可放在头文件中声明;但在C中,其声明则必须放在源文件(即.C文件中,在C中const声明一个变量,除了不能改变其值外,它仍是一具变量。.const_cast用法:const_cast《type_id》(expression)该运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,type_id和expression的类型是一样的。常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。.continuecontinue(继续关键字用于循环结构。它使程序跳过代码段后部的部分,与break不同的是,continue不是进入代码段后的部分执行,而是重新开始新的循环。因而它是“继续循环”之意,不是break(跳出。.defaultdefault(默认、缺省用于switch语句。当switch所有的case都不满足时,将进入default执行。default只能放在switch语句所有的case之后,并且是可选的。.deletedelete(删除释放程序动态申请的内存空间。delete后面通常是一个指针或者数组,并且只能delete通过new关键字申请的指针,否则会发生段错误。.dodo-while是一类循环结构。与while循环不同,do-while循环保证至少要进入循环体一次。.doubledouble(双精度类型,C++中的基本数据结构,以双精度形式存储一个浮点数。.dynamic_castdynamic_cast(动态转换,允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构安全地转换类型。dynamic_cast提供了两种转换方式,把基类指针转换成派生类指针,或者把指向基类的左值转换成派生类的引用。.elseelse紧跟在if后面,用于对if不成立的情况的选择。.enumenum(枚举类型,给出一系列固定的值,只能在这里面进行选择一个。.explicitexplicit(显式的的作用是“禁止单参数构造函数”被用于自动型别转换,其中比较典型的例子就是容器类型。在这种类型的构造函数中你可以将初始长度作为参数传递给构造函数。.export为了访问其他编译单元(如另一代码文件中的变量或对象,对普通类型(包括基本数据类、结构和类,可以利用关键字extern,来使用这些变量或对象时;但是对模板类型,则必须在定义这些模板类对象和模板函数时,使用标准C++新增加的关键字export(导出。.externextern(外部的声明变量或函数为外部链接,即该变量或函数名在其它文件中可见。被其修饰的变量(外部变量是静态分配空间的,即程序开始时分配,结束时释放。用其声明的变量或函数应该在别的文件或同一文件的其它地方定义(实现。在文件内声明一个变量或函数默认为可被外部使用。在C++中,还可用来指定使用另一语言进行链接,这时需要与特定的转换符一起使用。目前仅支持”C”转换标记,来支持C编译器链接。使用这种情况有两种形式:extern“C”声明语句extern“C”{声明语句块}.falsefalse(假的,C++的基本数据结构bool类型的值之一。等同于int的值。.floatfloat(浮点数,C++中的基本数据结构,精度小于double。.forfor是C++中的循环结构之一,用于有确定开始和结束以及需要确定步长的循环结构。.friendfriend(友元声明友元关系。友元可以访问与其有friend关系的类中的private/protected成员,通过友元直接访问类中的private/protected成员的主要目的是提高效率。友元包括友元函数和友元类。.gotogoto(转到,用于无条件跳转到某一标号处开始执行。.ifif(如果,C++中的条件语句之一,可以根据后面的bool类型的值选择进入一个分支执行。.inlineinline(内联函数的定义将在编译时在调用处展开。inline函数一般由短小的语句组成,可以提高程序效率。.intint(整型,integer,C++中的基本数据结构,用于表示整数,精度小于long。.longlong(长整型,longinteger,C++中的基本数据结构,用于表示长整数。.mutablemutable(易变的是C++中一个不常用的关键字。只能用于类的非静态和非常量数据成员。由于一个对象的状态由该对象的非静态数据成员决定,所以随着数据成员的改变,对像的状态也会随之发生变化。如果一个类的成员函数被声明为const类型,表示该函数不会改变对象的状态,也就是该函数不会修改类的非静态数据成员。但是有些时候需要在该类函数中对类的数据成员进行赋值,这个时候就需要用到mutable关键字。.namespacenamespace(命名空间用于在逻辑上组织类,是一种比类大的结构。.newnew(新建用于新建一个对象。new运算符总是返回一个指针。由new创建的对象需要在恰当的地方进行delete操作。.operatoroperator(操作符用于操作符重载。这是C++中的一种特殊的函数。.privateprivate(私有的,C++中的访问控制符。被标明为private的字段只能在本类以及友元中访问。.protectedprotected(受保护的,C++中的访问控制符。被标明为protected的字段只能在本类以及其继承类和友元中访问。.publicpublic(公有的,C++中的访问控制符。被标明为public的字段可以在任何类中进行访问。.registerregister(寄存器声明的变量称着寄存器变量,在可能的情况下会直接存放在机器的寄存器中;但对位编译器不起作用,当globaloptimizations(全局优化开的时候,它会做出选择是否放在自己的寄存器中;不过其它与register关键字有关的其它符号都对位编译器有效。.reinterpret_cast用法:reinpreter_cast《type-id》(expression)type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值。.returnreturn(返回用于在函数中返回值。程序在执行到return语句后立即返回,return后面的语句无法执行到。.shortshort(短整型,shortinteger,C++中的基本数据结构,用于表示整数,精度小于int。.signedsigned(有符号,表明该类型是有符号数,和unsigned相反。数字类型(整型和浮点型都可以用signed修饰。但默认就是signed,所以一般不会显式使用。.sizeof由于C++每种类型的大小都是由编译器自行决定的,为了增加可移植性,可以用sizeof运算符获得该数据类型占用的字节数。.staticstatic(静态的静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为,使用时可改变其值。静态变量或静态函数,只有本文件内的代码才可访问它,它的名字(变量名或函数名在其它文件中不可见。因此也称为“文件作用域”。在C++类的成员变量被声明为static(称为静态成员变量,意味着它被该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见;而类的静态成员函数也只能访问静态成员(变量或函数。类的静态成员变量必须在声明它的文件范围内进行初始化才能使用,private类型的也不例外。.static_cast用法:static_cast《type-id》(expression)该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:①用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示是安全的;进行下行转换(把基类指针或引用转换成子类表示时,由于没有动态类型检查,所以是不安全的。②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。③把空指针转换成目标类型的空指针。④把任何类型的表达式转换成void类型。注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。.structstruct(结构类型,类似于class关键字,与C语言兼容(class关键字是不与C语言兼容的,可以实现面向对象程序设计.switchswitch(转换类似于if-else-if语句,是一种多分枝语句。它提供了一种简洁的书写,并且能够生成效率更好的代码。但是,switch后面的判断只能是int(char也可以,但char本质上也是一种int类型。switch语句最后的default分支是可选的。其用法为:.templatetemplate(模板,C++中泛型机制的实现。.thisthis返回调用者本身的指针。.throwthrow(抛出用于实现C++的异常处理机制,可以通过throw关键字“抛出”一个异常。.truetrue(真的,C++的基本数据结构bool类型的值之一。等同于int的非值。.trytry(尝试用于实现C++的异常处理机制。可以在try中调用可能抛出异常的函数,然后在try后面的catch中捕获并进行处理。.typedeftypedef(类型定义,typedefine,其格式为:typedef类型定义名;类型说明定义了一个数据类型的新名字而不是定义一种新的数据类型。定义名表示这个类型的新名字。.typeid指出指针或引用指向的对象的实际派生类型。.typenametypename(类型名字关键字告诉编译器把一个特殊的名字解释成一个类型。在下列情况下必须对一个name使用typename关键字:.一个唯一的name(可以作为类型理解,它嵌套在另一个类型中的。.依赖于一个模板参数,就是说:模板参数在某种程度上包含这个name。当模板参数使编译器在指认一个类型时产生了误解。.unionunion(联合,类似于enum。不同的是enum实质上是int类型的,而union可以用于所有类型,并且其占用空间是随着实际类型大小变化的。.unsignedunsigned(无符号,表明该类型是无符号数,和signed相反。.using表明使用namespace。.virtualvirtual(虚的,C++中用来实现多态机制。.voidvoid(空的,可以作为函数返回值,表明不返回任何数据;可以作为参数,表明没有参数传入(C++中不是必须的;可以作为指针使用。.volatilevolatile(不稳定的限定一个对象可被外部进程(操作系统、硬件或并发线程等改变,声明时的语法如下:intvolatilenVint;这样的声明是不能达到最高效的,因为它们的值随时会改变,系统在需要时会经常读写这个对象的值。因此常用于像中断处理程序之类的异步进程进行内存单元访问。.wchar_twchar_t是宽字符类型,每个wchar_t类型占个字节,位宽。汉字的表示就要用到wchar_t。.whileC++中循环语句之一,和do…while不同之处在于while是在开始处进行判断的,因而可能一次都不进入循环。

  ⑹c++中的explicit关键字是什么意思

  ⑺用explicit关键字标示一个构造函数的话,就说明这个类的对象不允许在函数的参数传递过程中用调用这类构造函数。(因为编译器默认的是会调用这样的构造函数的比如:classA{public:A(inttar){}};voidtar_func(Aa){}然后在main函数中有:intmain(){tar_func();//这里参数是一个整形,会调用A的构造函数,并生成一个A类的对象return;}如果构造函数前面加了explict那么这种main函数中的调用方法就是错误的了。

  ⑻explicit是什么意思

  ⑼显式地,C++提供了关键字explicit,声明为explicit的构造函数不能用于隐式转换。等级测试{公共:test(intn){num=n;}//通用构造函数私人:intnum};等级测试{公共:explicittest(intn){num=n;}//显式构造函数私人:intnum};intmain(){Testt=//隐式调用其构造函数,成功Testt=//编译错误,无法隐式调用其构造函数。testT();//显式调用成功返回;}都是复制粘贴,因为问题比较简单。怎么能省事呢?一站式出国留学攻略

  ⑽能解释下c++的explicit关键字的作用吗

  ⑾关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。C++中,一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数),承担了两个角色。是个构造器是个默认且隐含的类型转换操作符。所以,有时候在我们写下如AAA=XXX,这样的代码,且恰好XXX的类型正好是AAA单参数构造器的参数类型,这时候编译器就自动调用这个构造器,创建一个AAA的对象。这样看起来好象很酷,很方便。但在某些情况下(见下面权威的例子,却违背了我们(程序员的本意。这时候就要在这个构造器前面加上explicit修饰,指定这个构造器只能被明确的调用,使用,不能作为类型转换操作符被隐含的使用。呵呵,看来还是光明正大些比较好。explicit构造函数的作用解析:explicit构造函数是用来防止隐式转换的。请看下面的代码:classTest{public:Test(intn){num=n;}//普通构造函数private:intnum;};classTest{public:explicitTest(intn){num=n;}//explicit(显式)构造函数private:intnum;};intmain(){Testt=;//隐式调用其构造函数,成功Testt=;//编译错误,不能隐式调用其构造函数Testt();//显示调用成功return;}Test的构造函数带一个int型的参数,代码行会隐式转换成调用Test的这个构造函数。而Test的构造函数被声明为explicit(显式,这表示不能通过隐式转换来调用这个构造函数,因此代码行会出现编译错误。普通构造函数能够被隐式调用。而explicit构造函数只能被显示调用。

  ⑿C++中explicit抑制构造函数定义的隐式转换按理下边的直接初始化也有类型转换啊,为什么不报错

  ⒀explicit主要用于防止隐式转换,用于修饰构造函数、复制构造函数;Aa(.);//这里.是作为形参对象,这里会隐式发生形参的数据类型转换,但仍符合构造函数要求Aa=.;//这里.是作为对象,明显不符A类的初始化构造函数;

  ⒁c++explicit的作用

  ⒂简单说就是用在构造函数前面禁止隐式类型转换比如classcls{explicitcls(inti){...}};另外有一个函数voidf(clsobj){...}inti=;这时候调用f(i)就是错误的没有explicit的话就可以用i隐式建立一个对象这样做(显示调用构造函数就是对的:clsobj(i);

  ⒃推荐先看书系统学习下吧《C++程序设计》一、C++类的定义C++中使用关键字class来定义类,其基本形式如下:class类名{行为或属性行为或属性行为或属性};示例:定义一个点(Point)类,具有以下属性和方法:■属性:x坐标,y坐标■方法:.设置x,y的坐标值;.输出坐标的信息。实现代码:classPoint{public:voidsetPoint(intx,inty);voidprintPoint();private:intxPos;intyPos;};代码说明:上段代码中定义了一个名为Point的类,具有两个私密属性,int型的xPos和yPos,分别用来表示x点和y点。在方法上,setPoint用来设置属性,也就是xPos和yPos的值;printPoint用来输出点的信息。数据抽象和封装抽象是通过特定的实例抽取共同特征以后形成概念的过程。一个对象是现实世界中一个实体的抽象,一个类是一组对象的抽象。封装是将相关的概念组成一个单元,然后通过一个名称来引用它。面向对象封装是将数据和基于数据的操作封装成一个整体对象,对数据的访问或修改只能通过对象对外提供的接口进行。类定义几个重要名词:()类名遵循一般的命名规则;字母,数字和下划线组合,不要以数字开头。()类成员类可以没有成员,也可以定义多个成员。成员可以是数据、函数或类型别名。所有的成员都必须在类的内部声明。没有成员的类是空类,空类也占用空间。classPeople{};sizeof(People)=;()构造函数构造函数是一个特殊的、与类同名的成员函数,用于给每个数据成员设置适当的初始值。()成员函数成员函数必须在类内部声明,可以在类内部定义,也可以在类外部定义。如果在类内部定义,就默认是内联函数。类定义补充.可使用类型别名来简化类除了定义数据和函数成员之外,类还可以定义自己的局部类型名字。使用类型别名有很多好处,它让复杂的类型名字变得简单明了、易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。classPeople{public:typedefstd::stringphonenum;//电话号码类型phonenumphonePub;//公开号码private:phonenumphonePri;//私人号码};.成员函数可被重载可以有多个重载成员函数,个数不限。.内联函数有三种:(直接在类内部定义。(在类内部声明,加上inline关键字,在类外部定义。(在类内部声明,在类外部定义,同时加上inline关键字。注意:此种情况下,内联函数的定义通常应该放在类定义的同一头文件中,而不是在源文件中。这是为了保证内联函数的定义在调用该函数的每个源文件中是可见的。.访问限制public,private,protected为属性/方法限制的关键字。.类的数据成员中不能使用auto、extern和register等进行修饰,也不能在定义时进行初始化如intxPos=;//错;例外:静态常量整型(包括char,bool数据成员可以直接在类的定义体中进行初始化,例如:stationstintia=;类声明与类定义.类声明(declare)classScreen;在声明之后,定义之前,只知道Screen是一个类名,但不知道包含哪些成员。只能以有限方式使用它,不能定义该类型的对象,只能用于定义指向该类型的指针或引用,声明(不是定义使用该类型作为形参类型或返回类型的函数。voidTest(Screen&a){};voidTest(Screen*a){};.类定义(define)在创建类的对象之前,必须完整的定义该类,而不只是声明类。所以,类不能具有自身类型的数据成员,但可以包含指向本类的指针或引用。classLinkScreen{public:Screenwindow;LinkScreen*next;LinkScreen*prev;};//注意,分号不能丢因为在类定义之后可以接一个对象定义列表,可类比内置类型,定义必须以分号结束:classLinkScreen{/*...*/};classLinkScreen{/*...*/}scr,scr;类对象定义类对象时,将为其分配存储空间。Sales_itemitem;//编译器分配了足以容纳一个Sales_item对象的存储空间。item指的就是那个存储空间。隐含的this指针成员函数具有一个附加的隐含形参,即this指针,它由编译器隐含地定义。成员函数的函数体可以显式使用this指针。.何时使用this指针当我们需要将一个对象作为整体引用而不是引用对象的一个成员时。最常见的情况是在这样的函数中使用this:该函数返回对调用该函数的对象的引用。classScreen{...public:Screen&set(char);};Screen&Screen::set(charc){contents=c;return*this;}类作用域每个类都定义了自己的作用域和唯一的类型。类的作用域包括:类的内部(花括号之内,定义在类外部的成员函数的参数表(小括号之内)和函数体(花括号之内。classScreen{//类的内部...};//类的外部charScreen::get(indexr,indexc)const{indexrow=r*width;//putetherowlocationreturncontents;//offsetbyctofetchspecifiedcharacter}注意:成员函数的返回类型不一定在类作用域中。可通过类名::来判断是否是类的作用域,::之前不属于类的作用域,::之后属于类的作用域。例如Screen::之前的返回类型就不在类的作用域,Screen::之后的函数名开始到函数体都是类的作用域。classScreen{public:typedefstd::string::size_typeindex;indexget_cursor()const;};Screen::indexScreen::get_cursor()const//注意:index前面的Screen不能少{returncursor;}该函数的返回类型是index,这是在Screen类内部定义的一个类型名。在类作用域之外使用,必须用完全限定的类型名Screen::index来指定所需要的index是在类Screen中定义的名字。二构造函数构造函数是特殊的成员函数,用来保证每个对象的数据成员具有合适的初始值。构造函数名字与类名相同,不能指定返回类型(也不能定义返回类型为void,可以有-n个形参。在创建类的对象时,编译器就运行一个构造函数。构造函数可以重载可以为一个类声明的构造函数的数量没有限制,只要每个构造函数的形参表是唯一的。classSales_item;{public:Sales_item(conststd::string&);Sales_item(std::istream&);Sales_item();//默认构造函数};构造函数自动执行只要创建该类型的一个对象,编译器就运行一个构造函数:Sales_itemitem(“---“);Sales_item*p=newSales_item();第一种情况下,运行接受一个string实参的构造函数,来初始化变量item。第二种情况下,动态分配一个新的Sales_item对象,通过运行默认构造函数初始化该对象。构造函数初始化式与其他函数一样,构造函数具有名字、形参表和函数体。与其他函数不同的是,构造函数可以包含一个构造函数初始化列表:Sales_item::Sales_item(conststring&book):isbn(book),units_sold(),revenue(.){}构造函数初始化列表以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在圆括号中的初始化式。构造函数可以定义在类的内部或外部。构造函数初始化只在构造函数的定义中指定。构造函数分两个阶段执行:()初始化阶段;()普通的计算阶段。初始化列表属于初始化阶段(),构造函数函数体中的所有语句属于计算阶段()。初始化列表比构造函数体先执行。不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化。.哪种类需要初始化式const对象或引用类型的对象,可以初始化,但不能对它们赋值,而且在开始执行构造函数的函数体之前要完成初始化。初始化const或引用类型数据成员的唯一机会是构造函数初始化列表中,在构造函数函数体中对它们赋值不起作用。没有默认构造函数的类类型的成员,以及const或引用类型的成员,必须在初始化列表中完成初始化。classConstRef{public:ConstRef(intii);private:inti;constintci;int&ri};ConstRef::ConstRef(intii){i=ii;//okci=ii;//errorri=i;//}应该这么初始化:ConstRef::ConstRef(intii):i(ii),ci(i),ri(ii){}.成员初始化的次序每个成员在构造函数初始化列表中只能指定一次。重复初始化,编译器一般会有提示。成员被初始化的次序就是定义成员的次序,跟初始化列表中的顺序无关。.初始化式表达式初始化式可以是任意表达式Sales_item(conststd::string&book,intt,doubleprice):isbn(book),units_sold(t),revenue(t*price){}.类类型的数据成员的初始化式初始化类类型的成员时,要指定实参并传递给成员类型的一个构造函数,可以使用该类型的任意构造函数。Sales_item():isbn(,’’),units_sold(),revenue(.){}.类对象的数据成员的初始化在类A的构造函数初始化列表中没有显式提及的每个成员,使用与初始化变量相同的规则来进行初始化。类类型的数据成员,运行该类型的默认构造函数来初始化。内置或复合类型的成员的初始值依赖于该类对象的作用域:在局部作用域中不被初始化,在全局作用域中被初始化为。假设有一个类A,classA{public:intia;Bb;};A类对象Aa;不管a在局部作用域还是全局作用域,b使用B类的默认构造函数来初始化,ia的初始化取决于a的作用域,a在局部作用域,ia不被初始化,a在全局作用域,ia初始化。默认构造函数不含形参的构造函数就是默认构造函数。只要定义一个对象时没有提供初始化式,就使用默认构造函数。如:Aa;为所有形参提供默认实参的构造函数也定义了默认构造函数。例如:classA{public:A(inta=,charc=’’){}private:intia;charc;};.合成的默认构造函数只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数。一个类只要定义了一个构造函数,编译器也不会再生成默认构造函数。建议:如果定义了其他构造函数,也提供一个默认构造函数。如果类包含内置或复合类型(如int&或string*的成员,它应该定义自己的构造函数来初始化这些成员。每个构造函数应该为每个内置或复合类型的成员提供初始化。隐式类类型转换.只含单个形参的构造函数能够实现从形参类型到该类类型的一个隐式转换classA{public:A(inta){ia=a;}boolEqualTo(constA&a){returnia==a.ia;}private:intia;};Aa();boolbEq=false;bEq=a.EqualTo();//参数为,实现从int型到A的隐式转换.抑制由构造函数定义的隐式转换通过将构造函数声明为explicit,来防止在需要隐式转换的上下文中使用构造函数:classA{public:explicitA(inta){ia=a;}boolEqualTo(constA&a){returnia==a.ia;}private:intia;};通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为explicit。将构造函数设置为explicit可以避免错误。三复制控制复制构造函数.几个要点()复制构造函数复制构造函数是一种特殊构造函数,只有个形参,该形参(常用const&修饰是对该类类型的引用。classPeopel{public:Peopel();//默认构造函数Peopel(constPeopel&);//复制构造函数~Peopel();//析构函数};当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。Peopela;Peopela=a;当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。PeopelFunc(Peopelb){...}()析构函数析构函数是构造函数的互补:当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放构造对象时或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都自动执行类中非static数据成员的析构函数。()复制控制复制构造函数、赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。()两种初始化形式C++支持两种初始化形式:直接初始化和复制初始化。直接初始化将初始化式放在圆括号中,复制初始化使用=符号。对于内置类型,例如int,double等,直接初始化和复制初始化没有区别。对于类类型:直接初始化直接调用与实参匹配的构造函数;复制初始化先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。直接初始化比复制初始化更快。()形参和返回值当形参或返回值为类类型时,由该类的复制构造函数进行复制。()初始化容器元素复制构造函数可用于初始化顺序容器中的元素。例如:vector《string》svec();编译器首先使用string默认构造函数创建一个临时值,然后使用复制构造函数将临时值复制到svec的每个元素。()构造函数与数组元素如果没有为类类型数组提供元素初始化式,则将用默认构造函数初始化每个元素。如果使用常规的花括号括住的数组初始化列表来提供显式元素初始化式,则使用复制初始化来初始化每个元素。根据指定值创建适当类型的元素,然后用复制构造函数将该值复制到相应元素:Sales_itemprimer_eds={string(“---“),string(“---“),string(“---“),Sales_item()};.合成的复制构造函数()合成的复制构造函数如果没有定义复制构造函数,编译器就会为我们合成一个。合成复制构造函数的行为是,执行逐个成员初始化,将新对象初始化为原对象的副本。逐个成员初始化:合成复制构造函数直接复制内置类型成员的值,类类型成员使用该类的复制构造函数进行复制。例外:如果一个类具有数组成员,则合成复制构造函数将复制数组。复制数组时合成复制构造函数将复制数组的每一个元素。.定义自己的复制构造函数()只包含类类型成员或内置类型(但不是指针类型成员的类,无须显式地定义复制构造函数,也可以复制。classPeopel{public:std::stringname;unsignedintid;unsignedintage;std::stringaddress;};()有些类必须对复制对象时发生的事情加以控制。例如,类有一个数据成员是指针,或者有成员表示在构造函数中分配的其他资源。而另一些类在创建新对象时必须做一些特定工作。这两种情况下,都必须定义自己的复制构造函数。最好显式或隐式定义默认构造函数和复制构造函数。如果定义了复制构造函数,必须定义默认构造函数。.禁止复制有些类需要完全禁止复制。例如,iostream类就不允许复制。延伸:容器内元素不能为iostream为了防止复制,类必须显式声明其复制构造函数为private。赋值操作符与复制构造函数一样,如果类没有定义自己的赋值操作符,则编译器会合成一个。()重载赋值操作符Sales_item&operator=(constSales_item&);()合成赋值操作符合成赋值操作符会逐个成员赋值:右操作数对象的每个成员赋值给左操作数对象的对应成员。除数组之外,每个成员用所属类型的常规方式进行赋值。对于数组,给每个数组元素赋值。()复制和赋值常一起使用一般而言,如果类需要复制构造函数,它也会需要赋值操作符。析构函数构造函数的用途之一是自动获取资源;与之相对的是,析构函数的用途之一是回收资源。除此之外,析构函数可以执行任意类设计者希望在该类对象的使用完毕之后执行的操作。()何时调用析构函数撤销(销毁类对象时会自动调用析构函数。变量(类对象在超出作用域时应该自动撤销(销毁。动态分配的对象(newA)只有在指向该对象的指针被删除时才撤销(销毁。撤销(销毁一个容器(不管是标准库容器还是内置数组时,也会运行容器中的类类型元素的析构函数(容器中的元素总是从后往前撤销。()何时编写显式析构函数如果类需要定义析构函数,则它也需要定义赋值操作符和复制构造函数,这个规则常称为三法则:如果类需要析构函数,则需要所有这三个复制控制成员。()合成析构函数合成析构函数按对象创建时的逆序撤销每个非static成员,因此,它按成员在类中声明次序的逆序撤销成员。对于每个类类型的成员,合成析构函数调用该成员的析构函数来撤销对象。合成析构函数并不删除指针成员所指向的对象。所以,如果有指针成员,一定要定义自己的析构函数来删除指针。析构函数与复制构造函数或赋值操作符之间的一个重要区别:即使我们编写了自己的析构函数,合成析构函数仍然运行。四友元友元机制允许一个类将对其非公有成员的访问权授予指定的函数或类。友元可以出现在类定义的内部的任何地方。友元不是授予友元关系的那个类的成员,所以它们不受声明出现部分的访问控制影响。建议:将友元声明成组地放在类定义的开始或结尾。友元类classHusband{public:friendclassWife;private:doublemoney;//钱是老公私有的,别人不能动,但老婆除外};classWife{public:voidConsume(Husband&h){h.money-=;//老婆可以花老公的钱}};Husbandh;Wifew;w.Consume(h);使其他类的成员函数成为友元classHusband;//.声明HusbandclassWife//.定义Wife类{public:voidConsume(Husband&h);};classHusband//.定义Husband类{public:friendvoidWife::Consume(Husband&h);//声明Consume函数。private:doublemoney;//钱是老公私有的,别人不能动,但老婆除外};voidWife::Consume(Husband&h)//.定义Consume函数。{h.money-=;//老婆可以花老公的钱}注意类和函数的声明和定义的顺序:()声明类Husband()定义类Wife,声明Consume函数()定义类Husband()定义Consume函数。

  ⒄c++中explicit有什么作用

  ⒅关键字explicit可以禁止“单参数构造函数”被用于自动类型转换classStack{explicitStack(intsize);};没有explicit的话Stacks=;能编译通过而有explicit则不能,必需Stacks();

您可能感兴趣的文章:

相关文章