C++ 隐式转换与explicit关键字

发布时间 2023-08-20 16:37:36作者: OrzMiku

隐式转换与explicit关键字

隐式转换

函数构造的隐式转换,直接上代码:

#include<bits/stdc++.h>

class Entity {
private:
	std::string m_Name;
	int m_Age;
public:
	Entity(const std::string& name)
		: m_Name(name), m_Age(-1) {}
	Entity(int age) 
	:m_Name("Unknown"), m_Age(age) {}
};

void printEntity(Entity e) {
	// some code to print entity
	// ...
}

int main() {
	printEntity(18);
	printEntity("OrzMiku");
}

我有一个 Entity 类,有两个私有成员变量 string类 m_Nameint类型 m_Age 用来表示名称和年龄。

接着有两个不同版本的构造函数,注意,这两个构造函数都有且只有一个参数传入。这里重点mark一下

然后有一个打印实体的函数 printEntity ,这个函数需要一个 Entity 类作为参数。

正常来说,我们可以这样调用这个函数:

	printEntity(Entity(22));
	printEntity(Entity("OrzMiku"));

这里有一个常见的隐式转换,是将char数组转换成string类。

但是注意上面的代码中,是这样调用这个函数的:

	printEntity(18);
	printEntity("OrzMiku");

其中,第一句是正确的,第二句是错误的。

第一句中直接传入了一个 int 类型,函数需要一个 Entity 类型,在 Entity 类中有一个构造函数的参数只需要一个int类型,这时就可以发生隐式转换。将 int 作为参数隐式转换成一个 Entity 类型。

第二句中直接传入了一个 char 数组,但是在Entity类中没有构造函数的参数只需要一个 char 数组。虽然有一个构造函数需要一个 string ,但是 char 数组到 stringstringEntity 需要两次转换,所以不能隐式转换。

第二句可以改成这样:

printEntity(std::string("OrzMiku"));

同理,我们在创建Entity实例的时候,也就可以这样:

Entity a = 18;
Entity b = std::string("OrzMiku");

虽然在C++中可以这样写,但是还是推荐不使用这样的隐式转换,虽然有时可以让代码看起来更加简洁,但是我觉得会大大降低代码的可读性

explicit关键字

正如前面所说,不推荐使用隐式转化。explicit关键字就可以禁止隐式转化。

用explicit关键字修饰一个构造函数,就意味着这个构造函数没有隐式转化,必须显式调用这个构造函数。上代码:

#include<bits/stdc++.h>

class Entity {
private:
	std::string m_Name;
	int m_Age;
public:
	Entity(const std::string& name)
		: m_Name(name), m_Age(-1) {}
	explicit Entity(int age) 
	:m_Name("Unknown"), m_Age(age) {}
};

void printEntity(Entity e) {
	// some code to print entity
	// ...
}

int main() {
	printEntity(18);
	printEntity(std::string("OrzMiku"));
}

还是刚刚那个代码,有一点点小小的改动,我们将Entity的一个构造函数用explicit关键词修饰了。此时底下的 printEntity(18); 这行就报错了。因为不能用explicit修饰了其对应的构造函数,这个构造函数现在必须显式调用了。

所以这句代码写成这样就好了:printEntity(Entity(18);