本文主要是介绍C++构造函数中explicit详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以...
在 C++ 编程中,构造函数是类的核心部分之一。我们常常使用构造函数来初始化对象。但是,如果不加限制,某些构造函数可能会被 隐式调用,从而带来一些意料之外的行为。
为了解决这个问题,C++ 提供了 explicit 关键字。
1. 什么是explicit
在 C++ 中,explicit 关键字用于修饰 单参数构造函数 或 可以看作单参数的构造函数,阻止编译器进行 隐式类型转换 或 拷贝初始化。
- 默认情况下,单参数构造函数既可以显式调用,也可以被编译器用来进行隐式类型转换。
explicit告诉编译器:这个构造函数只能显式调用,不能用于隐式转换。
2. 隐式转换的问题
来看一个例子:
#include <IOStream> using namespace std; class Fraction { private: int numerator; int denominator; public: Fraction(int num, int den = 1) : numerator(num), denominator(den) {} void print() const { cout << numerator << "/" << denominator << endl; } }; int main() { Fraction f1 = 5; // 隐式调用 Fraction(5, 1) f1.print(); // 输出:5/1 }
在上面的例子中:
Fraction f1 = 5;本质上是调用 China编程Fraction(5, 1),因为编译器允许用int隐式转换成Fraction。- 虽然看似方便,但有时会带来 不可控的隐式转换,导致逻辑错误或二义性。
3.explicit的使用示例
基本用法
如果我们在构造函数前加上 explicit:
class Fraction {
private:
int numerator;
int denominator;
public:
explicit Fraction(int num, int den = 1) : numerator(num), denominator(den) {}
vo编程id print() const {
cout << numerator << "/" << denominator << endl;
}
};
int main() {
Fraction f1(5); // ✅ 显式调用,可以
// Fraction f2 = 5; // ❌ 编译错误,不能隐式转换
}
Fraction f1(5);依然可以显式调用。- 但
Fraction f2 = 5;会报错,因为explicit禁止了隐式转换。
多参数构造函数
有时构造函数有多个参数,但如果除第一个外的参数都有默认值,它依然算作 单参数构造函数,也可能引发隐式转换。
class Fraction {
public:
explicit Fraction(int num, int den = 1) { /* ... */ }
};
这里如果没有 explicit,表达式 Fraction f = 5; 依然会成立。
4. C++11 之后的扩展
(1)explicit用于转换运算符
在 C++11 之前,类的类型转换函数(比如 operator bool)会允许隐式转换:
class Test {
public:
operator bool() const { return true; }
};
int main() {
Test t;
if (t) { // 隐式调用 operator bool()
cout << "True" << endl;
}
}
但有时我们并不希望这种隐式转换。C++javascript11 允许写成:
class Test {
public:
explicit operator bool() const { return true; }
};
int main() {
Test t;
// if (t) { } // ❌ 错误,不能隐式转换
if (static_cast<bool>(t)) { // ✅ 必须显式转换
cout << "True" << endl;
}
}
(2) C++20 的explicihttp://www.chinasem.cnt(bool)
C++20 引入了更灵活的语法:explicit(bool)。
这让我们可以根据编译期常量决定是否允许隐式调用。
struct A {
androidexplicit(true) A(int) {} // 永远显式
explicit(false) A(double) {} // 永远允许隐式
};
这种写法在模板编程中很有用。
5. 最佳实践
几乎总是给单参数构造函数加
explicit
这样可以避免隐式转换带来的混乱,除非你确实需要这种转换。转换运算符应当尽量显式
尤其是operator bool,因为隐式转换到bool可能导致奇怪的条件判断。允许隐式转换的场景
如果你的类本质上就是包装某个类型(比如string_view可以从const char*隐式转换),那么允许隐式转换可以让使用更加自然。
总结
- explicit 的主要作用:防止构造函数或转换运算符被隐式调用。
- 在单参数构造函数和转换运算符中使用最为常见。
- 自 C++11 起,还能用于 operator bool;C++20 引入 explicit(bool),进一步增强灵活性。
- 最佳实践:默认加上 explicit,除非你有充分理由允许隐式转换。
- 关键字explicit只对一个实参的构造函数有效,需要多个实参的构造函数不能用于执行隐式转换,所以无需将这些构造函数指定为explicit的。
- 只能在类内声明构造函数时使用explicit关键字。
补充
- 接受一个单参数的const char*的string构造函数不是explicit的
- 接受一个容量参数的vector构造函数是explicit的
到此这篇关于C++构造函数中explicit详解的文章就介绍到这了,更多相关C++构造函数explicit内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于C++构造函数中explicit详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!