目录
〇、构造函数还具有类型转换的作用
构造函数不仅可以构造与初始化对象,对于只有一个参数或只有第一个参数没有缺省值和全缺省的构造函数,还具有类型转换的作用。
eg. 将一个自定义类型赋值给一个自定义类型,触发类的隐式类型转换:
实际编译器背后会用1构造一个无名对象,然后调用拷贝构造函数用无名对象在创建a对象时初始化。(VS编译器对这个步骤进行了优化,可能观察不到。)
实际编译器背后会用2构造一个无名对象,然后调用赋值运算符重载用无名对象给b对象进行赋值。
所以类的隐式类型转换的原理是先调用构造函数创建一个无名对象,再传入这个无名对象调用拷贝构造函数或赋值运算符重载。
一、explicit关键字是什么?
explicit是C++中的一个关键字,它用来修饰只有一个参数的类构造函数(不是拷贝构造函数),以表明该构造函数是显式的,而非隐式的。当使用explicit修饰构造函数时,它将禁止类对象之间的隐式转换,即禁止类的隐式转换的第一步调用构造函数创建无名对象。
explicit只有在修饰完所有只有一个参数的类构造函数或只有第一个参数没有缺省值和全缺省的构造函数才能发挥禁止隐式类型转换的作用。
再次强调explicit修饰拷贝构造函数无法发挥禁止隐式类型转换的作用,explicit无法修饰赋值运算符重载。
eg. Date2的构造函数(注意修饰的是只有一个参数的构造函数,不是拷贝构造函数)被explicit修饰后,无法隐式转换:
这里实际上是禁用了编译器隐式调用拷贝构造函数。
eg. Date2的构造函数被explicit修饰后,无法隐式转换,只能显式地调用构造函数来创建对象:
二、为什么需要explicit关键字?
我们先如下代码,是否有可能会认为Date1是经typedf重命名的内置类型、PrintDate函数的参数是内置类型?
int main() { Date1 b = 1; PrintDate(1); return 0; }
但实际上它是这样的:
class Date1{ public: Date1(int m) { minute = m; } int minute; }; void PrintDate(const Date1& d){ cout << d.minute << endl; } int main() { Date1 b = 1; PrintDate(1); return 0; }
这样的代码的可读性和可维护性无疑是很差的,在多人合作的项目中极其容易引起误会。
如果上述代码使用了explicit关键字将构造函数声明为显式构造函数,则编译器将不再进行隐式类型转换,而会导致编译错误。这样可以避免一些意外的类型转换,提高代码的可读性和可维护性。
总的来说,explicit关键字的作用是确保类型转换的清晰和明确,避免不必要的、可能引发错误的隐式转换。
三、怎么使用explicit关键字?
explicit关键字在C++中只能用于修饰类的构造函数,它用来修饰只有一个参数的类构造函数,以表明该构造函数是显式的,而非隐式的。
只要在构造函数名前加上explicit就能禁止类对象之间的隐式转换、禁止隐式调用拷贝构造函数。
explicit只有在修饰完所有只有一个参数的类构造函数或只有第一个参数没有缺省值和全缺省的构造函数才能发挥禁止隐式类型转换的作用。
再次强调explicit修饰拷贝构造函数无法发挥禁止隐式类型转换的作用,explicit无法修饰赋值运算符重载。
eg. explicit关键字只能用于修饰构造函数:
【总结】
------------------------END-------------------------
才疏学浅,谬误难免,欢迎各位批评指正。