C 中EXPLICIT关键字的含义和用法
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
};
然后再编译:
$ gcc -S people.cpp
编译器立马报错:
people.cpp: In function ‘void foo()’:
没有进行任何显式的转换,直接将一个整型数据赋值给了类变量 p3.
不相信? 耳听为虚,眼见为实,让我们看看底层的实现方式。
为了更容易比较方式一和方式三的实现方式,我们对上面的代码作一点修改,去除方式二:
void foo ( void ) {
People p1(10); //方式一 People p3=10; //方式三 }
看“.LCFI4” 行后面的东西,1-4 行和 5-8 行几乎一模一样,1-4 行即为方式一的汇编 代码,5-8 即为方式三的汇编代码。 细心的你可能发现 2 和 6 行有所不同,一个是 -4(%ebp) 而另一个一个是 -8(%ebp) ,这分别为类变量 P1 和 P3 的地址。
对于不可随意进行类型转换的强类型语言 C/C++来说, 这可以说是 C++的一个特性。 哦,今天好像不是要说 C++的特性,而是要知道 explicit 关键字的作用?
//方式一 //方式二 //方式三,该句编译无法通过,系统会报错
这段 C++ 程序定义了一个类 people ,包含一个构造函数, 这个构造函数只包含一 个整形参数 a ,可用于在构造类时初始化 age 变量。
然后定义了一个函数 foo,在这个函数中我们用三种方式分别创建了三个 10 岁的“人”。 第一种是最一般的类变量声明方式。第二种方式其实是声明了一个 people 类的指针变量, 然后在堆中动态创建了一个 people 实例,并把这个实例的地址赋值给了 p_p2.第三种方式就 是我们所说的特殊方式,为什么说特殊呢? 我们都知道,C/C++是一种强类型语言,不同 的数据类型是不能随意转换的,如果要进行类型转换,必须进行显式强制类型转换,而这里,
C++中的 explicit 关键字用来修饰类的构造函数,表明该构造函数是显式的。
C++ 中 explicit 关键字的作用
在 C++ 中, 如果一个类有 [只有一个参数] 的构造函数,C++ 允许一种特殊的声明 类变量的方式。在这种情况下,可以直接将一个对应于构造函数参数类型的数据直接赋值给 类变量,编译器在编译时会自动进行类型转换,将对应于构造函数参数类型的数据转换为类 的对象。 如果在构造函数前加上 explicit 修饰词, 则会禁止这种自动转换,在这种情况下, 即使将对应于构造函数参数类型的数据直接赋值给类变量,编译器也会报错。
下面以具体ቤተ መጻሕፍቲ ባይዱ例来说明。 建立 people.cpp 文件,然后输入下列内容:
class People {
public: int age; explicit People (int a)
{ age=a;
} };
void foo ( void ) {
People p1(10); People* p_p2=new People(10); People p3=10; }
explicit 关键字到底是什么作用呢? 它的作用就是禁止这个特性。如文章一开始而言, 凡是用 explicit 关键字修饰的构造函数,编译时就不会进行自动转换,而会报错。
让我们看看吧! 修改代码:
class People {
public: int age; explicit People (int a) { age=a; }
去除方式二的原因是方式二是在堆上动态创建类实例,因此会有一些额外代码影响分 析。修改完成后,用下列命令编译 people.cpp
$ gcc -S people.cpp
"-S"选项是 GCC 输出汇编代码。命令执行后,默认生成 people.s。 关键部分内容如下:
.globl _Z3foov .type _Z3foov, @function _Z3foov: .LFB5: pushl %ebp .LCFI2: movl %esp, %ebp .LCFI3: subl $24, %esp .LCFI4: movl $10, 4(%esp) leal -4(%ebp), %eax movl %eax, (%esp) call _ZN6PeopleC1Ei movl $10, 4(%esp) leal -8(%ebp), %eax movl %eax, (%esp) call _ZN6PeopleC1Ei leave ret
然后再编译:
$ gcc -S people.cpp
编译器立马报错:
people.cpp: In function ‘void foo()’:
没有进行任何显式的转换,直接将一个整型数据赋值给了类变量 p3.
不相信? 耳听为虚,眼见为实,让我们看看底层的实现方式。
为了更容易比较方式一和方式三的实现方式,我们对上面的代码作一点修改,去除方式二:
void foo ( void ) {
People p1(10); //方式一 People p3=10; //方式三 }
看“.LCFI4” 行后面的东西,1-4 行和 5-8 行几乎一模一样,1-4 行即为方式一的汇编 代码,5-8 即为方式三的汇编代码。 细心的你可能发现 2 和 6 行有所不同,一个是 -4(%ebp) 而另一个一个是 -8(%ebp) ,这分别为类变量 P1 和 P3 的地址。
对于不可随意进行类型转换的强类型语言 C/C++来说, 这可以说是 C++的一个特性。 哦,今天好像不是要说 C++的特性,而是要知道 explicit 关键字的作用?
//方式一 //方式二 //方式三,该句编译无法通过,系统会报错
这段 C++ 程序定义了一个类 people ,包含一个构造函数, 这个构造函数只包含一 个整形参数 a ,可用于在构造类时初始化 age 变量。
然后定义了一个函数 foo,在这个函数中我们用三种方式分别创建了三个 10 岁的“人”。 第一种是最一般的类变量声明方式。第二种方式其实是声明了一个 people 类的指针变量, 然后在堆中动态创建了一个 people 实例,并把这个实例的地址赋值给了 p_p2.第三种方式就 是我们所说的特殊方式,为什么说特殊呢? 我们都知道,C/C++是一种强类型语言,不同 的数据类型是不能随意转换的,如果要进行类型转换,必须进行显式强制类型转换,而这里,
C++中的 explicit 关键字用来修饰类的构造函数,表明该构造函数是显式的。
C++ 中 explicit 关键字的作用
在 C++ 中, 如果一个类有 [只有一个参数] 的构造函数,C++ 允许一种特殊的声明 类变量的方式。在这种情况下,可以直接将一个对应于构造函数参数类型的数据直接赋值给 类变量,编译器在编译时会自动进行类型转换,将对应于构造函数参数类型的数据转换为类 的对象。 如果在构造函数前加上 explicit 修饰词, 则会禁止这种自动转换,在这种情况下, 即使将对应于构造函数参数类型的数据直接赋值给类变量,编译器也会报错。
下面以具体ቤተ መጻሕፍቲ ባይዱ例来说明。 建立 people.cpp 文件,然后输入下列内容:
class People {
public: int age; explicit People (int a)
{ age=a;
} };
void foo ( void ) {
People p1(10); People* p_p2=new People(10); People p3=10; }
explicit 关键字到底是什么作用呢? 它的作用就是禁止这个特性。如文章一开始而言, 凡是用 explicit 关键字修饰的构造函数,编译时就不会进行自动转换,而会报错。
让我们看看吧! 修改代码:
class People {
public: int age; explicit People (int a) { age=a; }
去除方式二的原因是方式二是在堆上动态创建类实例,因此会有一些额外代码影响分 析。修改完成后,用下列命令编译 people.cpp
$ gcc -S people.cpp
"-S"选项是 GCC 输出汇编代码。命令执行后,默认生成 people.s。 关键部分内容如下:
.globl _Z3foov .type _Z3foov, @function _Z3foov: .LFB5: pushl %ebp .LCFI2: movl %esp, %ebp .LCFI3: subl $24, %esp .LCFI4: movl $10, 4(%esp) leal -4(%ebp), %eax movl %eax, (%esp) call _ZN6PeopleC1Ei movl $10, 4(%esp) leal -8(%ebp), %eax movl %eax, (%esp) call _ZN6PeopleC1Ei leave ret