C++ 隐式的类类型转换

2018-02-03 10:19:01来源:网络收集作者:程序诗人人点击

分享

转换构造函数

  如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制,有时我们把这种构造函数称作为转换构造函数。


实例
#include "stdafx.h"
#include
#include
using namespace std;
class Animal
{
public:
Animal(string name):m_name(name) {}
// 比较动物的名字
bool isSame(Animal animal)
{
return m_name == animal.m_name;
}
private:
string m_name;
};
int main()
{
Animal dog("dog");
// 打印为 1
cout << dog.isSame(string("dog")) << endl;
getchar();
return 0;
}

  在示例中定义接受 string 的构造函数就是定义了从 string 类型向Animal隐式转换的规则。编译器用给定的 string 参数自动创建了一个 Animal对象,新生成的这个临时 Animal 对象被传递给 isSame,然后进行比较。


只允许一步类类型转换

  编译器只会自动地执行一步类型转换。如果我们把上例中的dog.isSame(string(“dog”)) 换成dog.isSame(“dog”), 那么编译器就会报错:


“不存在从 “const char [4]” 转换到 “Animal” 的适当构造函数”,因为它经历了两步转换。


从 “dog”转换成 string
从 string转换成Animal

因此我们可以这样做:


// 显示地转换成 string,隐式地转换成 Animal
dog.isSame(string("dog"));
// 或者
// 隐式地转换成 string, 显示地转换成 Animal
dog.isSame(Animal("dog"));
隐式转换的副作用

  有时隐式转换会带来很大的副作用,比如,标准库中的 vector 的接受一个容量参数的构造函数是禁止隐式转换的,如果不禁止,那么


std::vector a(5)


可声明一个初始长度为5的vector,但是这样写


std::vector a=5


就也是可以的了。极大地降低了可读性。


禁止隐式转换

  我们可以将构造函数声明为 explicit 来禁止隐式转换。而且 explicit 构造函数只能用于直接初始化即当我们执行拷贝形式的初始化时(使用=)时不允许的。
如果我们不加 explicit:


Animal dog("dog"); // 正确
Animal cat = "cat"; // 正确 发生隐式类类型转换
dog.isSame(string("dog")); // 正确 发生隐式类类型转换

如果我们加上 explicit:


Animal dog("dog"); // 正确
Animal cat = "cat"; // 错误 不允许隐式类类型转换
dog.isSame(string("dog")); // 错误 不允许隐式类类型转换
// 可以显示的进行类类型转换
Animal cat = Animal("cat"); // 正确
dog.isSame(Animal("dog")); // 正确

  所以标准库中的 vector 的接受一个容量参数的构造函数是禁止隐式转换的,声明了构造函数为 explicit。
  关键字 explicit 只对一个实参的构造函数有效。需要多个实参的构造函数不能用于隐式转换,所以无须将这些构造函数指定为 explicit 的。只能在类内声明构造函数时使用 explicit 关键字,在类外部定义时不应重复。


参考 《C++ primer》第五版


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台