C++ explicit
explicit
关键字有两个用途:
- 指定构造函数或者转换函数(C++11起)为显示,即它不用用于隐式转换和赋值初始化。
- 可以与常量表达式一同使用。当该表达式为true才为显示转换(C++20起)。
1.将构造函数标记为显式
C++中的explicit
关键字通常用来将构造函数标记为显式类型转换,即在创建对象的时候不能进行隐式转换。
可以通过一个例子理解:
/*************************************************************************
> File Name: 01.cpp
> Author:
> Mail:
> Created Time: Mon 18 Sep 2023 02:12:16 PM CST
************************************************************************/
#include <iostream>
using namespace std;
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0.0, double i = 0.0)
: real(r)
, imag(i)
{
}
bool operator==(Complex rhs)
{
return (real == rhs.real && imag == rhs.imag)
? true
: false;
}
};
int main()
{
Complex com1(3.0, 0.0);
if (com1 == 3.0)
cout << "Same" << endl;
else
cout << "Not Same" << endl;
return 0;
}
编译并执行:
ydqun@ydqhost explicit % g++ 01-without-explicit.cpp [0]
ydqun@ydqhost explicit % ./a.out [0]
Same
在上述例子中,main函数里构建了com1实例,并且用com1和double类型的3.0进行比较,此时double类型的3.0被隐式转换成Complex类型。
我们可以避免这种隐式转换,因为它们可能会导致意外的结果。我们可以通过explicit关键字使构造函数变成显式。例如,如果我们尝试使用以下带有explicit关键字的构造函数,就会出现编译错误。
#include <iostream>
using namespace std;
class Complex {
private:
double real;
double imag;
public:
explicit Complex(double r = 0.0, double i = 0.0)
: real(r)
, imag(i)
{
}
bool operator==(Complex rhs)
{
return (real == rhs.real && imag == rhs.imag)
? true
: false;
}
};
int main()
{
Complex com1(3.0, 0.0);
if (com1 == 3.0)
cout << "Same" << endl;
else
cout << "Not Same" << endl;
return 0;
}
给构造函数添加了explicit
关键字修饰后,此时编译会出现如下错误:
ydqun@ydqhost explicit % g++ 01-without-explicit.cpp [0]
01-without-explicit.cpp: In function ‘int main()’:
01-without-explicit.cpp:34:14: error: no match for ‘operator==’ (operand types are ‘Complex’ and ‘double’)
34 | if (com1 == 3.0)
| ~~~~ ^~ ~~~
| | |
| Complex double
01-without-explicit.cpp:22:10: note: candidate: ‘bool Complex::operator==(Complex)’
22 | bool operator==(Complex rhs)
| ^~~~~~~~
01-without-explicit.cpp:22:29: note: no known conversion for argument 1 from ‘double’ to ‘Complex’
22 | bool operator==(Complex rhs)
这时候需要我们进行显式转换。
#include <iostream>
using namespace std;
class Complex {
private:
double real;
double imag;
public:
explicit Complex(double r = 0.0, double i = 0.0)
: real(r)
, imag(i)
{
}
bool operator==(Complex rhs)
{
return (real == rhs.real && imag == rhs.imag)
? true
: false;
}
};
int main()
{
Complex com1(3.0, 0.0);
if (com1 == (Complex)3.0) //此处对double类型的3.0进行显式转换为Complex
cout << "Same" << endl;
else
cout << "Not Same" << endl;
return 0;
}
编译并输出:
ydqun@ydqhost explicit % g++ 02-with-explicit.cpp [0]
ydqun@ydqhost explicit % ./a.out [0]
Same
2.与常量表达式一同使用
explicit
关键字可以与常量表达式一起使用。但是,如果常量表达式的计算结果为true
,此时构造函数是显式的;否则,构造函数是
隐式的。
#include <iostream>
constexpr bool ENABLE_EXPLICIT = false;
class Foo {
public:
explicit(ENABLE_EXPLICIT)
Foo(int i) : m_i(i) {}
private:
int m_i;
};
int main()
{
Foo a = 1;
}
编译可以通过,但是如果把变量ENABLE_EXPLICIT
改为true
,则会出现如下编译错误:
ydqun@ydqhost explicit % g++ 03-explicit.cpp -std=c++2a [0]
03-explicit.cpp: In function ‘int main()’:
03-explicit.cpp:21:13: error: conversion from ‘int’ to non-scalar type ‘Foo’ requested
21 | Foo a = 1;
注意,编译以上例程需要在C++20及以上才能编译通过。
- explicitexplicitly explicit关键字 关键 component explicit rendered should emit declaration annotation explicit extraneous explicitly component children dependencies compatible intellij explicit 函数explicit annotation processors explicitly declared estextspotter transformer end explicit euler explicit implicit taylor