C++关键字:explicit简介

有一段时间没有写博客,最近一段时间一直在补自己的C++知识,尤其是面向对象的部分。昨晚在看CPP的时候发现了一个有趣的关键字:explicit

在区别explicit的使用之前,请先来简单地了解一下隐式转换和显示转换:

  • 隐式转换:在转换的时候不给系统提示具体的模型,让其自动转换,例如:
    int a = 10; float b = 12.7; b = a;   ----   这是把int类型转换为了float类型,由编译器自动完成的
  • 显示转换:类似于强制转换,例如:
    int a = 10; float b = (float) a;    ----  这是把int类型的强制转换成float类型的
  • 当类构造函数的参数只有一个的时候,或者所有参数都有默认值的情况下,类A的对象时可以直接被对应的内置类型隐式转换后去赋值的,这样会造成错误

看一个类构造的隐式换元的例子:

#include <iostream>
using namespace std;
class A
{
public:
	// 这个A类的构造函数是可以使用隐式转换的,可以将传递的int类型进行构造
	A(int num) : number(num){}
	void Show() const{
		cout << number << endl;
	}
private:
	int number;
};

void Func(const A& a){
	a.Show();
}

int main(int argc, char const *argv[])
{
	Func(119);
	return 0;
}

// 输出:119
// 可以看到:虽然在调用Func()函数的时候没有传递A类型的实例,但是仍然打印除了119
// 说明编译器自动进行了隐式转换

explicit 主要使用在类的构造函数前面起修饰作用,作用是禁止类构造函数的隐式换元

不使用explicit的情况:

// explicit - 阻止编译器使用这个构造函数做隐式转换
// ***不使用explicit的情况***
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
	// 这两个构造函数的参数不一样
	Person(string str) :  name(str){}
	Person(int _age) : age(_age){
		name = string(age, 'x');
	}
	~Person(){};
	void ShowStr() const{
		cout << name << endl;
	}
private:
	string name;
	int age;
};

// 定义一个执行函数 - 作用是创建一个打印一个Person对象的name,形式参数需要传递一个Person对
void PrintPersonName(const Person& p){
	p.ShowStr();
}

int main(int argc, char const *argv[])
{
	// 此时直接调用一个PrintPersonName函数 - 注意!传递的是一个int类型,按照正常参数传递来说是不正确的!!
	PrintPersonName(46);
	return 0;
}

输出:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// 可以看到:即使是错误的参数,仍然因为隐式转换的原因产生了正确的结果,这样不利于程序错误的排查
// 当类构造函数的参数只有一个的时候,或者所有参数都有默认值的情况下,类A的对象时可以直接被对应的内置类型隐式转换后去赋值的,这样会造成错误

使用explicit的情况:

// ***使用explicit的情况***
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
	// 这两个构造函数的参数不一样
	explicit Person(string str):name(str){}
	explicit Person(int _age):age(_age){
		name = string(age, 'x');
	}
	~Person(){};
	void ShowStr() const{
		cout << name << endl;
	}
private:
	string name;
	int age;
};

// 定义一个执行函数 - 作用是创建一个打印一个Person对象的name,形式参数需要传递一个Person对
void PrintPersonName(const Person& p){
	p.ShowStr();
}

int main(int argc, char const *argv[])
{
	// 此时直接调用一个PrintPersonName函数 - 注意!传递的是一个int类型,按照正常参数传递来说是不正确的!!
	PrintPersonName(46);
	return 0;
}

// 输出: 	invalid initialiation of reference of type 'const Person&' from expression of type 'int'
// 		 	in passing argument 1 of 'void PrintPersonName(const Person&)'
// 此时会报错,因为在使用了explicit关键字之后,禁止了编译器在使用构造函数的时候自动进行隐式转换
// explicit可以抑制内置类型隐式转换,所以在类的构造函数中,最好尽可能多用explicit关键字,防止不必要的隐式转换

参考:

https://blog.csdn.net/qq_36038987/article/details/77029044

https://blog.csdn.net/ftell/article/details/80418678

https://blog.csdn.net/qq_37233607/article/details/79051075

猜你喜欢

转载自blog.csdn.net/weixin_43826242/article/details/88546500