[cpp primer随笔] 15. 通过构造函数进行类类型的隐式转换

一、转换构造函数

当一个类A的构造函数,其参数列表仅存在一个其他类型B的参数(或者剩余参数存在默认实参),那么该构造函数被称之为转换构造函数。 该构造函数可用于将类型B转换为类型A,并且在参数传递、拷贝赋值等场景下,可以由编译器直接完成这一步隐式转换

class Info{
private:
	String name;
public:
	A(String name_): name(name_){};
};

String str = "Mollia";

Info info = str; // 成功
Info info = "Mollia"; // 失败,仅支持单步隐式转换

void test(Info info);
test(str); // 成功调用
test("Mollia"); // 错误,仅支持单步隐式转换
test(Info(str)); // 可以手动进行类类型转换

请注意:编译器仅可利用转换构造函数做出单步隐式转换。指的是如果C可以隐式转换为B,而B可隐式转换为A类型,那么编译器无法直接将C转换为A类型。但这不影响我们显式调用构造函数做出转换。

二、使用explicit关键字抑制隐式转换

有些情况下,由编译器自动执行的隐式转换可能与预期功能不符,此时可以将上述的转换构造函数使用explicit关键字进行修饰,这类构造函数具备以下特点:

  • 无法类类型隐式转换,但是仍然可以手动显式地执行转换
  • 只能用于直接初始化,无法用于拷贝初始化
class A{
private: 
    string name;
public:
    A() = default;
    explict A(string name_): name(name_){};
};

void test(A &obj); // a function defination called `test`

test(string(“ben”)); // 错误: explicit关键字修饰的构造函数无法对参数类型对象进行隐式类型转换
test(A(“ben”)); //  正确:但是不影响我们显式调用进行转换

A obj1; //  默认构造
A obj2 = obj1; //  错误:explicit关键字修饰的构造函数无法被用于拷贝初始化
A obj3(“name”); //  而只能使用直接初始化

绝佳例子:
标准库类型string具备一个单参数的const char* 类型的非explicit构造函数,因此我们可以直接:string a = "aaa";。与之相反地,vector有一个单参数explicit构造函数,参数指定了初始容量大小,因此无法通过隐式类型转换得到,这就是explicit使用的一个正确场景,因为将一个数字隐式转化成一个vector这件事情听起来就很炸裂。

你可能感兴趣的:(C++,c++)