深入理解C++ explicit关键字

深入理解C++ explicit关键字 1.explicit的核心作用explicit的中文意思是“明确的、显式的”。它用在构造函数或 C11 之后的类型转换运算符前面作用是禁止编译器进行隐式类型转换。换句话说加了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_castBar(200)); // 3. 显式临时对象构造没问题 printBar(Bar(300)); // 下面两行如果取消注释**编译会报错** // 因为 Bar 的构造函数是 explicit编译器禁止把 int 偷偷转成 Bar。 // // printBar(400); // 错误不能从 int 隐式转换到 Bar // Bar b2 500; // 错误复制初始化不允许调用 explicit 构造函数 return 0; }