explicit关键字的作用

合集下载

关键字explicit的作用

关键字explicit的作用

explicit构造函数C++编程语言中有很多比较重要的关键字在实际编程中起着非常重要的作用。

我们今天为大家介绍的C++ explicit关键字就是其中一个应用比较频繁的关键字。

下面就让我们一起来看看这方面的知识吧。

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:class MyClass{public:MyClass( int num );}//.MyClass obj = 10; //ok,convert int to MyClass在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:MyClass temp(10);MyClass obj = temp;上面的所有的C++ explicit关键字相关的操作即是所谓的"隐式转换"。

如果要避免这种自动转换的功能,这就是关键字explicit的作用了,将类的构造函数声明为"显式",也就是在声明构造函数的时候前面添加上explicit即可,这样就可以防止这种自动的转换操作,如果我们修改上面的MyClass类的构造函数为显式的,那么下面的代码就不能够编译通过了,如下所示:class MyClass{public:explicit MyClass( int num );}//.MyClass obj = 10; //err,can't non-explict convert以上就是对C++ explicit关键字的相关介绍。

explicit用来防止由构造函数定义的隐式转换。

要明白它的作用,首先要了解隐式转换:可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个隐式转换。

C++构造函数、复制构造函数和析构函数专题(修订版)

C++构造函数、复制构造函数和析构函数专题(修订版)
本文作者:黄邦勇帅(编著)(原名:黄勇) 本文是学习 C++中的最基本的内容,因此学习 C++就应全部掌握本文的内容。在知道了怎样声明一个类之后,就会遇 到关于构造函数的问题,本文是关于构造函数的专题,介绍了构造函数,重点讲解了成员初始化列表和析构函数,并 对复制构造函数、直接初始化、复制初始化、赋值、临时对象之间的关系作了深入讲解,本文内容全面,简单易懂。 本文使用的是 x86 机器(主流计算机都是 x86 机器),windows xp 操作系统,VC++2005 编译器进行讲解的。 本文内容完全属于个人见解与参考文现的作者无关,限于水平有限,其中难免有误解之处,望指出更正。 声明:禁止抄袭,复印,转载本文,本文作者拥有完全版权。 主要参考文献: 1、C++.Primer.Plus.第五版.中文版 [美]Stephen Prata 著 孙建春 韦强译 人民邮电出版社 2005 年 5 月 2、C++.Primer.Plus.第四版.中文版 Stanley B.Lippman、Barbara E.Moo 著 李师贤等译 人民邮电出版社 2006 年 3 月 3、C++.Primer.Plus.第三版.中文版 Stanley B.Lippman 等著 潘爱民 张丽译 中国电力出版社 2002 年 5 月 4、 《高质量 C++编程指南》 作者 林锐 出版社不详 2001 年 7 月 5、 《C++程序设计》 作者 谭浩强 清华大学出版社 2004 年 6 月
示例:构造函数和Biblioteka 认构造函数#include <iostream> #include <string> using namespace std; class A{public: //void A(){} //A()const{} //A1(){} A(){cout<<"A"<<endl;} A(int i){cout<<"Ai"<<endl;} }; //构造函数一般被声明为公有的,因为主要是用来初始化对象的数据成员的 //错误,构造函数不能反回任何值(包括void类型) //错误,构造函数不能是const或volatile的 //错误,构造函数的名称必须与类名相同。 //正确,构造函数可以有形参也可以没有形参 //正确,可以重载多个构造函数的版本

c++中 explicit关键字的含义和用法

c++中 explicit关键字的含义和用法

上面的所有的操作即是所谓的"隐式转换".
如果要避免这种自动转换的功能,我们该怎么做呢?嘿嘿这就是关键字explicit的作用了,将类的构造函数声明为"显示",也就是在声明构造函数的时候 前面添加上explicit即可,这样就可以防止这种自动的转换操作,如果我们修改上面的MyClass类的构造函数为显示的,那么下面的代码就不能够编 译通过了,如下所示:
{
public:
MyClass( int num );
}
....
MyClass obj = 10; //ok,convert int to MyClass
在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:
MyClass temp(10);
MyClass obj = temp;
Sales_item& operator+(const Sales_item &lhs,const Sales_item rhs){if(!lhs.same_isbn(rhs)) throw isbn_mismatch("isbn missmatch",lhs.book(),rhs.book());Sales_item ret(lhs);ret+rhs;return ret;}
The implicit type conversion of const char * to a string object enables its users to write the following:string s;s = "Hello";The compiler implicitly transforms this intostring s;//pseudo C++ code:s = string ("Hello"); //create a temporary and assign it to sOn the other hand, if you declare this constructor explicit, you have to use explicit type conversion:class string{//...public:explicit string(const char *);};int main(){string s;s = string("Hello"); //explicit conversion now requiredreturn 0;}Extensive amounts of legacy C++ code rely on the implicit conversion of constructors. The C++ Standardizationcommittee was aware of that. In order to not make existing code break, the implicit conversion was retained. However, anew keyword, explicit, was introduced to the languageto enable the programmer to block the implicit conversionwhen it is undesirable. As a rule, a constructor that can be invoked with a single argument needs to be declaredexplicit. When the implicit type conversion is intentional and well behaved, the constructor can be used as animplicit conversion operator.

explicit 用法

explicit 用法

explicit 用法explicit关键字作用:禁止隐式调用类的单参数的构造函数。

上述实际上由两种情形:1. 禁止隐式调用拷贝构造函数2. 禁止类对象之间的隐式转换。

类对象间的隐式转换:利用一个已经存在的其他类型的对象来创建本类的新对象,且不显示调用本类的构造函数。

案例:#include <iostream>using namespace std;class A{public:A(){num = 9000;}A(int n){this->num = n;}A(const A&a){num = a.num;}friend void show(const A&);private:int num;};void show(const A& a){cout << "a.num = "<< a.num << endl;}int main(){// 隐式调用类A的单参的构造器cout << "Hello world!" << endl;A a1 = 5000;//调用隐式转换构造器A a2 = a1;//调用隐式拷贝构造器show(a1);show(a2);show(6000);return 0;}上述隐式调用C++语法是允许的,但很多人对这种表示方式不习惯,觉得程序的可读性较差。

为了禁止对类的单参数构造器的隐式调用,C++引入关键字explicit。

在类的定义中,在任何一个单参数构造器前加explicit,即可以禁止对该构造器的隐式调用。

案例:#include <iostream>using namespace std;class A{public:A(){num = 0;}explicit A(int n){this->num = n;}explicit A(const A& a){num = a.num;}friend void show(const A&);private:int num;};void show(const A& a){cout << " variable:" << a.num << endl;}int main(){//cout << "Hello world!" << endl;A a1(32);A a2(a1);show(a1);show(a2);show(A(6000));return 0;}这样程序既可以正常运行,并具有更好的可读性。

必会常用关键字

必会常用关键字

C#常用关键字1)abstract 可以和类、方法、属性、索引器及事件一起使用,标识一个可以扩展但不能被实体化的、必须被实现的类或方法。

2)as 一个转换操作符,如果转换失败,就返回null。

3)base 用于访问被派生类或构造中的同名成员隐藏的基类成员。

4)catch 定义一个代码块,在特定类型异常抛出时,执行块内代码。

参见try和finally。

5)checked 既是操作符又是语句。

确保编译器运行时,检查整数类型操作或转换时出现的溢出。

6)const 标识一个可在编译时计算出来的变量值,即一经指派不可修改的值。

7)delegate 指定一个声明为一种委托类型。

委托把方法封装为可调用实体,能在委托实体中调用。

8)enum 表示一个已命名常量群集的值类型。

9)event 允许一个类或对象提供通知的成员,他必须是委托类型。

10)explicit 一个定义用户自定义转换操作符的操作符,通常用来将内建类型转换为用户定义类型或反向操作。

必须再转换时调用显示转换操作符。

11)extern 标识一个将在外部(通常不是c#语言)实现的方法。

12)finally 定义一个代码块,在程序控制离开try代码快后执行。

参见try和catch。

13)fixed 在一个代码块执行时,在固定内存位置为一个变量指派一个指针。

14)foreach 用于遍历一个群集的元素。

15)goto 一个跳转语句,将程序执行重定向到一个标签语句。

16)implicit 一个操作符,定义一个用户定义的转换操作符。

通常用来将预定义类型转换为用户定义类型或反向操作。

隐式转换操作符必须在转换时使用。

17)interface 将一个声明指定为接口类型,即实现类或构造必须遵循的合同。

18)internal 一个访问修饰符。

19)namespace 定义一个逻辑组的类型和命名空间。

20)operator 用来声明或多载一个操作符。

21)out 标识一个参数值会受影响的参数,但在传入方法时,该参数无需先初始化。

c语言32个关键字详解

c语言32个关键字详解

c语言32个关键字详解auto: auto关键字是c语言中用来声明局部变量的修饰符,它能够使程序员在一个函数的内部定义一个局部变量。

auto关键字的作用是使得这个局部变量在函数返回后不会消失,而是可以在函数的外部继续存在。

break: break关键字用于强制跳出循环,它可以用于while,do while或者for循环。

当它出现在循环内部时,循环立即终止,并且控制流程将会跳转到循环外部。

case: case关键字可以用来创建一个条件分支,并且它必须出现在switch语句中。

它可以使得程序不必以多重if语句来处理多重分支问题。

char: char关键字用来指定字符变量,它可以表示一个字符或者一个小整数,一般8位字节足以存放一个字符。

const: const关键字用来定义常量,它之后的变量不能被修改,一旦定义的常量将一直保存在程序的整个执行过程中。

continue: continue关键字用来结束当前迭代循环,并且进入下一次迭代循环。

当它出现在循环内部时,当前的循环将会立即终止,控制流程将会继续到循环的下一个迭代中。

default: default关键字用来指定switch中的默认case语句,当没有任何case匹配成功时,将会执行default后面的语句。

do: do关键字用来声明一个do-while循环,do-while循环通常用来保证在程序中某个条件至少被执行一次,它的基本形式为“do{}while()”,执行流程大致如下:首先执行do后面的语句,然后判断while后面的条件是否满足,如果满足,则继续执行do后面的语句,直到while条件不成立。

double: double关键字用来指定双精度浮点类型的变量,它能够表示一个比较大的数字,一般来说8个字节存储就足够了。

else: else关键字用来指定if语句的反条件分支,即当if检查的条件不满足时,会执行else后面的语句。

enum: enum关键字用来指定一组枚举类型的常量,它可以使枚举的常量有规律的递增或者递减,常用于建立某一种特定事物的有限集合。

c#转换关键词explicit的使用

c#转换关键词explicit的使用

c#转换关键词explicit的使用c#转换关键词explicit的使用引导语:C#适合为独立和嵌入式的系统编写程序,从使用复杂操作系统的大型系统到特定应用的小型系统均适用。

以下是店铺整理的c#转换关键词explicit的使用,欢迎参考阅读!explicit 关键字用于声明必须使用强制转换来调用的用户定义的类型转换运算符。

例如,在下面的示例中,此运算符将名为Fahrenheit 的类转换为名为 Celsius 的`类:C#// Must be defined inside a class called Farenheit:public static explicit operator Celsius(Fahrenheit f){return new Celsius((5.0f / 9.0f) * (f.degrees - 32));}可以如下所示调用此转换运算符:C#Fahrenheit f = new Fahrenheit(100.0f);Console.Write("{0} fahrenheit", f.Degrees);Celsius c = (Celsius)f;转换运算符将源类型转换为目标类型。

源类型提供转换运算符。

与隐式转换不同,必须通过强制转换的方式来调用显式转换运算符。

如果转换操作可能导致异常或丢失信息,则应将其标记为 explicit。

这可以防止编译器无提示地调用可能产生无法预见后果的转换操作。

省略此强制转换将导致编译时错误编译器错误 CS0266。

示例下面的示例提供 Fahrenheit 和 Celsius 类,它们中的每一个都为另一个提供显式转换运算符。

C#class Celsius{public Celsius(float temp){degrees = temp;}public static explicit operator Fahrenheit(Celsius c) {return new Fahrenheit((9.0f / 5.0f) * c.degrees + 32); }public float Degrees{get { return degrees; }}private float degrees;}class Fahrenheit{public Fahrenheit(float temp){degrees = temp;}// Must be defined inside a class called Farenheit: public static explicit operator Celsius(Fahrenheit f) {return new Celsius((5.0f / 9.0f) * (f.degrees - 32));}public float Degrees{get { return degrees; }}private float degrees;}class MainClass{static void Main(){Fahrenheit f = new Fahrenheit(100.0f);Console.Write("{0} fahrenheit", f.Degrees);Celsius c = (Celsius)f;Console.Write(" = {0} celsius", c.Degrees);Fahrenheit f2 = (Fahrenheit)c;Console.WriteLine(" = {0} fahrenheit", f2.Degrees);}}/*Output:100 fahrenheit = 37.77778 celsius = 100 fahrenheit*/下面的示例定义一个结构Digit,该结构表示单个十进制数字。

c++中explicit的用法

c++中explicit的用法

C++中explicit的用法1. 介绍在C++编程中,explicit是一个关键字,用于修饰构造函数。

它的作用是禁止编译器执行自动类型转换,以避免意外的类型转换造成的不确定性和错误。

在本文中,将对explicit的用法进行详细介绍,并举例说明其在实际编程中的应用。

2. explicit的基本概念在C++中,当一个构造函数只接受一个参数时,它实际上定义了一个从该参数类型到类类型的隐式类型转换。

这种隐式类型转换可能会导致一些潜在的问题,比如不期望的类型转换或者不明确的代码逻辑。

为了解决这些问题,C++11引入了explicit关键字,用于显式声明构造函数为显式构造函数,从而禁止编译器执行隐式类型转换。

3. explicit的使用方法在类的构造函数声明前加上explicit关键字,即可将该构造函数声明为显式构造函数。

例如:```cppclass Test {public:explicit Test(int value) : m_value(value) {}private:int m_value;};```在上面的例子中,Test类的构造函数接受一个int类型的参数,但加上了explicit关键字,表示该构造函数为显式构造函数,禁止编译器执行隐式类型转换。

4. 显式构造函数的优势通过使用explicit关键字声明构造函数,我们可以有效地避免一些潜在的问题,例如:- 避免意外的类型转换:对于只接受一个参数的构造函数,如果不使用explicit关键字,那么它将成为隐式类型转换的候选函数,这可能导致意外的类型转换,从而产生错误的结果。

- 明确代码逻辑:显式构造函数可以使代码的逻辑更加明确,使得代码阅读和维护更加容易。

5. 显式构造函数的应用场景显式构造函数通常适用于以下情况:- 构造函数只接受一个参数,并且该参数不能被隐式转换为类的类型。

- 需要避免意外的类型转换和提高代码的可读性。

6. 总结在C++编程中,显式构造函数是一个非常有用的特性,它可以有效地避免一些潜在的问题,提高代码的可靠性和可维护性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

谈谈explicit关键字
2004-08-19 20:35 16677人阅读评论(7) 收藏举报
今天看到公司的代码内有大量的explicit关键字,但是老版的MSDN内例子并不完善,实在是不明白,最终从网上一篇文章内找到了答案:原来explicit是为了防止隐式使用拷贝构造函数的.以下附上从新版MSDN中找到的例子和网上那篇文章:
// Copy From MSDN
This keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object.
The following program will fail to compile because of the explicit keyword. To resolve the error, remove the explicit keywords and adjust the code in g.
// spec1_explicit.cpp
// compile with: /EHsc
#include
class C
{
public:
int i;
explicit C(const C&) // an explicit copy constructor
{
printf("/nin the copy constructor");
}
explicit C(int i ) // an explicit constructor
{
printf("/nin the constructor");
}
C()
{
i = 0;
}
};
class C2
{
public:
int i;
explicit C2(int i ) // an explicit constructor
{
}
};
C f(C c)
{ // C2558
c.i = 2;
return c; // first call to copy constructor
}
void f2(C2)
{
}
void g(int i)
{
f2(i); // C2558
// try the following line instead
// f2(C2(i));
}
int main()
{
C c, d;
d = f(c); // c is copied
}
Note explicit on a constructor with multiple arguments has no effect, since
such constructors cannot take part in implicit conversions. However, for the
purpose of implicit conversion, explicit will have an effect if a constructor has
multiple arguments and all but one of the arguments has a default value.
// Copy From Internet Article
Pointer
不看书不知道自己的C++有多差T_T,看到explicit 时遇到一个问题。

请看下面一段程序:class A{
public:
A(int i) : m_i(i){}
int m_i;
};
int main(){
A a = 0;
a = 10; // 这里是什么操作?
}
这个操作产生了一个临时对象。

我怀疑是默认赋值运算符“A &operator = (int i){}”,于是重载了一下该运算符,结果确实运行到重载的运算符函数里了,那么临时对象又是如何产生的呢?
难道默认的赋值运算符是这样操作的?
A &operator = (int i){
A a(i);
return a;
}
这让我想起了类似的函数操作:
void fn(A a){
// ...
}
这里可以直接写fn(10);也是产生了一个临时对象。

难道真的是这样吗?忘解惑。

alexeyomux
老兄你用的是哪个编译器?在我印象之中,好像标准C++并不会给出operator =啊。

等我去试一试。

gongminmin
当然会有默认的operator=了
按照c++标准,编译器会生成五个默认成员函数:
默认构造函数
拷贝构造函数
析构函数
operator=
operator&
千里马肝
class A
{
public:
A(int i) : m_i(i){}
int m_i;
};
分别说说吧:
1. A a = 0;
首先, compiler认为这样写是不符合规矩的, 因为A = A才是正常行为。

但是她并不放弃, 通过搜索, 发现A可以根据一个int构造, 同时这个A(int i)没有用explicit修饰过。

那么A a = 0; 这样的一句话随即转变成:
A tmp(0);
A a = tmp;
需要说明的是, A a = tmp是调用的copy ctor, 虽然class A中并没有, 但是通常不写copy ctor的话,
compiler都会生成一个memberwise assignment操作性质的ctor, 底层实现通常会以memcpy进行。

2. a = 10;
首先, 这样同ctor的情况一样, compiler无法直接进行操作。

类推, 等同于代码:
A tmp(10);
a = tmp;
需要注意的是, a = tmp是调用的assignment操作, 同ctor一样,我们自己不写, 编译器同样进行
memberwise assignment操作。

3. fn(A a)
同样, fn(10)也是不对的, 但是"按照惯例", 呵呵, 会有:
A tmp(10);
fn(tmp);
另外, 为你解惑:
copy ctor的写法只能是T::T(const T &);
而assignment的写法可以多变, 即任意. 以T为例,
可以有
T &operator = (int n);
也可有
T &operator = (const char *);
当然, 你要确认如此的定义是对T而言有意义.
然后, 上述a = tmp, 即调用的默认的、标准的、自动生成的T &operator = (const T &). 开销是会有一个临时的A tmp生成, 然后memcpy.
但如果你自已写了T &operator = (int n), 那么a = 10即意味着a.m_i = 10.
当然, 以开销而言要视你的T &operator = (int n)是否为inline了.
对于explicit, 当修饰explicit A(int i) : m_i(i){}, 那么即告诉compiler不要在私底下做那么多的转换动作.
而且自动生成如A tmp(0)这样的东西是我们不想要的, 因为某些情况下自动转换这种行为是错误的.
最后, 相关此类问题, 还有一个话题, 即class A可以有operator int(), 会在fn(int n){}
A a(3);
fn(a)
起到魔术般的作用. 关于这个, 留给你自己看看书吧:)
最后,祝学习C++的路上一帆风顺。

Good luck~。

相关文档
最新文档