C++11之显式转换操作符-explicit
Posted 林夕07
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11之显式转换操作符-explicit相关的知识,希望对你有一定的参考价值。
系列文章
C++11之正则表达式(regex_match、regex_search、regex_replace)
C++11之线程库(Thread、Mutex、atomic、lock_guard、同步)
C++11之智能指针(unique_ptr、shared_ptr、weak_ptr、auto_ptr)浅谈内存管理
C++11之强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)
C++11之右值引用:移动语义和完美转发(带你了解移动构造函数、纯右值、将亡值、右值引用、std::move、forward等新概念)
文章目录
隐式类型转换
在C++中存在着一把双刃剑—隐式类型转型。好处是可以编写过多的构造函数,坏处是总会有一些意外情况并非程序员所愿。
场景1
下面分别实现了有无被explicit
关键字修饰的类和函数。
#include <iostream>
using std::cout;
using std::endl;
class Rational1
public:
Rational1(int n = 0, int d = 1):num(n), den(d)
cout << __func__ << "(" << num << "/" << den << ")" << endl;
public:
int num; // 被除数
int den; // 除数
;
class Rational2
public:
explicit Rational2(int n = 0, int d = 1) :num(n), den(d)
cout << __func__ << "(" << num << "/" << den << ")" << endl;
public:
int num; // 被除数
int den; // 除数
;
void Display1(Rational1 r)
cout << __func__ << endl;
void Display2(Rational2 r)
cout << __func__ << endl;
int main()
Rational1 r1 = 11;
Rational1 r2(11);
Rational2 r3 = 11; // error E0415
Rational2 r4(11);
Display1(1);
Display2(2); // error E0415
return 0;
运行报错:这是因为Rationl2这个类没有对应int参数的构造函数。
在这里,并没有体现出explicit的优点,甚至觉得有它使得代码更加麻烦。但是我们必须要阻止那种带有歧义的隐式类型转换。
场景2
这里的例子来自C++11提案,但有一些细微的变动。定义了一个Ptr
类,并实现了bool
类型转换。这样我们就可以很方便使用if(p)
来判断指针是否有效。但是带来的坏处就是支持Ptr对象的相加运算,例如 p + pd
。
#include <iostream>
using std::cout;
using std::endl;
template<class T>
class Ptr
public:
Ptr(T* p) :m_p(p)
operator bool() const
return m_p != nullptr ? true : false;
private:
T* m_p;
;
int main()
int a = 11;
Ptr<int> p(&a);
if(p)
cout << "valid pointer." << endl; // 有效的指针
else
cout << "invalid pointer." << endl; // 无效的指针
Ptr<int> pd(0);
cout << p + pd << endl;
cout << pd << endl;
return 0;
运行结果:
valid pointer.
1
0
很明显这并不是我们想要的结果。这时我们只需要使用explicit
关键字修饰到bool类型转换上就可以有效的防止这种”意外“发生。
在bool运算符重载中添加explicit
运行结果:
没有找到接受’Ptr(int>'类型左操作数的操作符(或者没有可接受的转换)。
场景3
这里定义了一个ConvertTo和Convertable类。在Convertable类中有一个显式转换到ConverTo类的方法。
#include <iostream>
using std::cout;
using std::endl;
class ConvertTo;
class Convertabkle
public:
explicit operator ConvertTo() const
return ConvertTo();
;
void Func(ConvertTo ct)
int main()
Convertabkle c;
ConvertTo ct(c);
ConvertTo ct2 = c; // 拷贝构造函数 error
ConvertTo ct3 = static_cast<ConvertTo>(c); // C++11的强制类型转换
Func(c); // 拷贝构造函数 error
return 0;
那么这样就会使得只有直接初始化或者使用强制类型转换才可以进行转换,不能再通过拷贝构造函数隐式转换了。
总结
1、从上面几个例子中,可以看出显示类型转换explicit
关键字并没有完全禁止从源类型到目标类型的转换,只是不允许拷贝构造函数和隐式类型转换罢了。所以我们就不能通过复制发方式或者通过函数参数的形式进行从源类型到目标类型的转换。
2、所以我们有必要在创建类时及时添加explicit
关键字,禁止隐式类型转换。
以上是关于C++11之显式转换操作符-explicit的主要内容,如果未能解决你的问题,请参考以下文章