C++ explicit
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及以上才能编译通过。