前言:
现在朋友们对“关键字不能作为什么来使用”大致比较看重,大家都想要学习一些“关键字不能作为什么来使用”的相关资讯。那么小编在网上收集了一些对于“关键字不能作为什么来使用””的相关内容,希望我们能喜欢,看官们快快来学习一下吧!前言:
C++ explicit关键字
在 C++ 中,explicit 关键字用于限制构造函数的隐式转换。当声明一个带有 explicit 关键字的单参数构造函数时,它就不能被用于隐式的类型转换。这对于防止意外的类型转换非常有用,特别是在类的设计中,可以避免因构造函数被误用而导致的潜在问题。
隐式构造 vs 显式构造
隐式构造:是指在不需要显式调用构造函数的情况下,编译器自动进行的类型转换。例如,从一个类型到另一个类型的自动转换。
显式构造:是指显式调用构造函数来创建对象的过程。这通常是通过构造函数名后面跟括号 () 或初始化列表 {} 来完成的。
explicit用法
explicit 关键字用于单参数构造函数前,如下所示:
class MyClass {public: explicit MyClass(int value) { // 构造函数实现 }};
示例
#include <iostream>class MyClass {public: explicit MyClass(int value) { data = value; } void printData() const { std::cout << "Data: " << data << std::endl; }private: int data;};int main() { // 显式构造 MyClass obj1(10); obj1.printData(); // 输出: Data: 10 // 隐式构造将导致编译错误 // MyClass obj2 = 20; // 错误: explicit 关键字禁止了隐式转换 // 显式构造 MyClass obj3(30); obj3.printData(); // 输出: Data: 30 return 0;}
在这个例子中,MyClass 的构造函数带有 explicit 关键字,这意味着不能使用它来进行隐式的类型转换。例如,代码27行 MyClass obj2 = 20; 这样赋值会导致编译错误。
都说关键字 explicit 只对一个实参的构造函数有效。其实也有例外:
多参数构造函数
对于多参数构造函数,如果只有一个参数没有默认值,那么这样的构造函数也可以被用作单参数构造函数。在这种情况下,explicit 关键字可以用于该构造函数,以防止隐式转换。
示例
#include <iostream>class MyClass {public: // 多参数构造函数,其中一个参数有默认值 explicit MyClass(int value, double precision = 0.0) : data(value), precision(precision) { std::cout << "Initialized with value: " << value << " and precision: " << precision << std::endl; } void printData() const { std::cout << "Data: " << data << ", Precision: " << precision << std::endl; }private: int data; double precision;};int main() { MyClass obj1(10); // 显式构造 obj1.printData(); // 输出: Data: 10, Precision: 0 // 编译错误:explicit 关键字禁止了隐式转换 MyClass obj2 = 20; // 错误: explicit 关键字禁止了隐式转换 MyClass obj3(20, 0.5); // 显式构造 obj3.printData(); // 输出: Data: 20, Precision: 0.5 getchar(); return 0;}
在这个例子中,构造函数 MyClass(int value, double precision = 0.0) 可以通过一个参数来调用,因为 precision 参数有默认值。通过使用 explicit 关键字,可以防止该构造函数被用于隐式类型转换。示例当中代码25行会报错。
使用复制列表初始化,explicit也能生效
示例
#include <iostream>class MyClass {public: // 多参数构造函数 explicit MyClass(int value, double precision): data(value), precision(precision) { std::cout << "Initialized with value: " << value << " and precision: " << precision << std::endl; } void printData() const { std::cout << "Data: " << data << ", Precision: " << precision << std::endl; } private: int data; double precision;};int main() { MyClass obj1{ 20, 0.5 }; // 显式 直接初始化构造 obj1.printData(); // 输出: Data: 20, Precision: 0.5 MyClass obj2 = { 20, 0.5 }; //报错 初始化 obj2.printData(); MyClass obj3(20, 0.5); // 显式构造 直接初始化 obj3.printData(); // 输出: Data: 20, Precision: 0.5 getchar(); return 0;}
示例代码27行报错
错误 C3445 "MyClass" 的复制列表初始化不能使用显式构造函数 0710 E:\src_20220311\1027\0710\0710.cpp 27
可以看到,加上explicit关键字做修饰,同样可以起到【禁止类型转换】的作用。
这里还有个小知识点:只能在类内声明构造函数时使用 explicit 关键字,在类外部定义时不应重复
//mya.hclass MyA{public: explicit MyA(int k);};
//mya.cpp#include "MyA.h"explicit MyA::MyA(int k){}
报错:
错误 C2178 不能使用“explicit”说明符声明“MyA::{ctor}”
题外话:
我个人一直都比较讨厌C++的这种隐式转换,有时候会出现和你想的不一样的情况,增加了学习成本。(高手写的代码应该是新手都能很清晰的看懂,但是实际情况是高手各种炫技,写的你看不懂才能显示出他是高手)
google的c++规范中提到explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit。例如作为其他类的透明包装器的类。(缺点无 不能再同意了)
effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。
标签: #关键字不能作为什么来使用