1.explicit的核心作用
explicit 的中文意思是“明确的、显式的”。它用在构造函数(或 c++11 之后的类型转换运算符)前面,作用是:
禁止编译器进行隐式类型转换。
换句话说:加了 explicit,编译器就不允许把别的类型“偷偷”变成你的类对象了;你必须明明白白地写出类型名来构造。
2. 为什么需要它?
如果不加 explicit,一个单参数的构造函数会变成一个“隐式转换工厂”。编译器看到 func(10),如果函数参数需要 myclass,它会自动调用 myclass(int) 帮你创建一个临时对象。
这在某些情况下非常方便(比如 std::string s = "hello";),但在大多数自定义类中,这种“自动变魔术”会掩盖代码的真实意图,甚至引发难以发现的 bug。
加 explicit 的目的:强制你显式地写 myclass(10),增强代码的清晰度和安全性。
#include <iostream>
#include <string>
// 定义一个没有 explicit 的类(允许隐式转换)
class foo {
public:
int value;
// 普通构造函数,没有 explicit
foo(int n) : value(n) {}
};
// 定义一个有 explicit 的类(禁止隐式转换)
class bar {
public:
int value;
// 加上 explicit 关键字
explicit bar(int n) : value(n) {}
};
// ---------- 测试函数 ----------
void printfoo(foo f) {
std::cout << "foo value: " << f.value << std::endl;
}
void printbar(bar b) {
std::cout << "bar value: " << b.value << std::endl;
}
int main() {
std::cout << "===== 测试没有 explicit 的 foo =====" << std::endl;
// 1. 直接构造,没问题
foo f1(10);
printfoo(f1);
// 2. 隐式构造!编译器把 int(20) 悄悄变成了 foo(20),
// 因为 foo 的构造函数没有 explicit,所以这行编译通过!
printfoo(20);
// 3. 复制初始化,同样触发隐式转换
foo f2 = 30;
std::cout << "f2.value: " << f2.value << std::endl;
std::cout << "\n===== 测试加了 explicit 的 bar =====" << std::endl;
// 1. 直接构造,没问题(显式调用,允许)
bar b1(100);
printbar(b1);
// 2. 显式强制转换,没问题(因为是你主动写的)
printbar(static_cast<bar>(200));
// 3. 显式临时对象构造,没问题
printbar(bar(300));
// 下面两行如果取消注释,**编译会报错**!!!
// 因为 bar 的构造函数是 explicit,编译器禁止把 int 偷偷转成 bar。
//
// printbar(400); // 错误!不能从 int 隐式转换到 bar
// bar b2 = 500; // 错误!复制初始化不允许调用 explicit 构造函数
return 0;
}到此这篇关于深入理解c++ explicit关键字的文章就介绍到这了,更多相关c++ explicit关键字内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论