欢迎光临
我们一直在努力

c++学习笔记分享--explicit关键字

日常分享整合的学习笔记:

首先,explict 中文意思是 清楚明白的;易于理解的;明确的;直言的 ;显式;

在编程中:

explicit用来告诉编译器:“不要偷偷用这个构造函数做隐式类型转换!

1.先看一个反面例子(没有 explicit)

假设有一个类:

class Number {
public:
Number(int x) { // 只有一个参数的构造函数
value = x;
}
private:
int value;
};

void printNumber(Number n) {
// 假装打印一下…
}

int main() {
printNumber(42); // 这里发生了甚么?

}

printNumber(42); 

在这里你本来想传入一个Number类给printNumber,但你传错了

而且这里发生了隐式类型转换,等价于:

Number n = 42; //这个是可以编译过的,可以试一下并输出一下value成员变量,结果是42
//相当于调用构造函数 Number n(42);

这很奇怪对吧?

因为编译器看到 printNumber需要 Number对象,但你传了一个 int,恰好是Number类对应的构造函数参数,于是它会自动调用 Number(int)构造函数把 42变成 Number(42)。这就是隐式类型转换

加上 explicit 之后:

class Number {
public:
explicit Number(int x) { // 加了个 explicit
value = x;
}
private:
int value;
};

void printNumber(Number n) { /* … */ }

int main() {
// printNumber(42); // 这行现在会报错!
printNumber(Number(42)); // 必须显式构造,这样写才行
}

加了 explicit后,编译器不会再偷偷帮你把 42转换成 Number,你必须自己明确写出构造过程。这让代码意图更清晰,也避免了一些隐蔽的错误。

2. 多参数构造函数(C++11 起)

从 C++11 开始,explicit也可以用在多参数构造函数上。它的作用是禁止使用花括号初始化列表进行隐式转换。

class Point {
public:
explicit Point(int x, int y) : mx(x), my(y) {} //初始化列表
private:
int mx, my;
};

void draw(Point p) {}

int main() {
draw({1, 2}); // ❌ 错误:不能隐式转换
draw(Point{1, 2}); // ✅ 正确:显式构造
}

注意:这里说的是花括号初始化列表​ {1, 2}这种写法。如果是 draw(Point(1, 2))圆括号构造,本来就没有隐式转换的问题。

3.常见疑惑与陷阱

疑惑 1:explicit 会影响拷贝/移动构造函数吗?

不影响。​ explicit只影响普通构造函数和转换运算符。拷贝构造函数和移动构造函数即使加了 explicit,也不影响它们正常的拷贝/移动行为(但一般没人给它们加)。

class Foo {
public:
explicit Foo(int) {} // 普通构造,禁止隐式转换
// 拷贝构造函数不需要 explicit
Foo(const Foo&) = default;
};

疑惑 2:explicit 和 = default / = delete 一起用?

可以。比如你想禁止某些隐式转换,但仍然保留默认构造:

class Bar {
public:
explicit Bar(int) = default; // 显式构造且使用默认实现
Bar(double) = delete; // 完全禁止 double 类型的构造
};

疑惑 3:explicit 到底能不能提高性能?

通常不能。​ explicit不影响运行时的性能,它只影响编译器的行为——是否允许某种写法通过编译。所以不用担心加了 explicit会让程序变慢

疑惑 4:什么时候应该不加 explicit?

很少见,但有几种情况可以考虑不加:

  • 包装类:比如一个类只是对底层类型的一层薄包装,而且经常需要和底层类型互操作。例如 std::string_view可以用 const char*隐式构造。

  • 数值类型:比如你自己写的 BigInteger类,允许 int隐式转换成它,可能会方便一些。

  • 仿函数/适配器:某些设计模式里,隐式转换反而让代码更简洁。

  • 不过作为新手,先一律加 explicit,等你真的遇到需要去掉的情况再改,这样最安全。

    4.什么时候用?

    建议:所有单参数构造函数都建议加上 explicit,除非你有非常明确的理由需要隐式转换(这种情况极少)。

    比如标准库里的 std::vector有一个 explicit vector(size_t count),就是为了防止你不小心写出这样的代码:

    std::vector<int> v = 10; // 如果没有 explicit,这行可能就编译过了,但语义很奇怪

    End………….

    如果这篇笔记对你有帮助,留下赞蟹蟹

    赞(0)
    未经允许不得转载:171主机测评 » c++学习笔记分享--explicit关键字
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址