C++中explicit详解

举报
码事漫谈 发表于 2025/06/30 13:54:10 2025/06/30
【摘要】 1. 防止隐式类型转换 示例1:没有使用explicit 示例2:使用explicit 2. 防止拷贝初始化 示例1:没有使用explicit 示例2:使用explicit 3. 防止隐式类型转换的链式调用 示例1:没有使用explicit 示例2:使用explicit 4. 防止隐式类型转换的歧义 示例1:没有使用explicit 示例2:使用explicit 总结在C++中,expli...

在C++中,explicit关键字用于修饰构造函数和转换运算符,其主要目的是防止隐式类型转换和拷贝初始化,从而提高代码的可读性和安全性。以下是explicit的详细作用和使用场景:

1. 防止隐式类型转换

当构造函数被声明为explicit时,它不能用于隐式类型转换。这意味着不能通过单个参数的构造函数隐式地将一个类型转换为另一个类型。

示例1:没有使用explicit

class MyClass {
public:
    MyClass(int x) : value(x) {} // 非explicit构造函数
    int value;
};

void printMyClass(MyClass obj) {
    std::cout << obj.value << std::endl;
}

int main() {
    printMyClass(10); // 隐式调用 MyClass(int) 构造函数
    return 0;
}

在这个例子中,MyClass(int)构造函数是非explicit的,因此可以隐式地将int类型转换为MyClass类型。调用printMyClass(10)时,会隐式地调用MyClass(10)构造函数。

示例2:使用explicit

class MyClass {
public:
    explicit MyClass(int x) : value(x) {} // explicit构造函数
    int value;
};

void printMyClass(MyClass obj) {
    std::cout << obj.value << std::endl;
}

int main() {
    // printMyClass(10); // 错误:无法隐式调用 MyClass(int) 构造函数
    printMyClass(MyClass(10)); // 显式调用 MyClass(10) 构造函数
    return 0;
}

在这个例子中,MyClass(int)构造函数被声明为explicit,因此不能隐式地将int类型转换为MyClass类型。调用printMyClass(10)时,会报错,必须显式地调用MyClass(10)构造函数。

2. 防止拷贝初始化

explicit构造函数不能用于拷贝初始化,但可以用于直接初始化。

示例1:没有使用explicit

class MyClass {
public:
    MyClass(int x) : value(x) {} // 非explicit构造函数
    int value;
};

int main() {
    MyClass obj = 10; // 拷贝初始化,隐式调用 MyClass(int) 构造函数
    return 0;
}

在这个例子中,MyClass(int)构造函数是非explicit的,因此可以用于拷贝初始化。

示例2:使用explicit

class MyClass {
public:
    explicit MyClass(int x) : value(x) {} // explicit构造函数
    int value;
};

int main() {
    // MyClass obj = 10; // 错误:无法隐式调用 MyClass(int) 构造函数
    MyClass obj(10); // 直接初始化,显式调用 MyClass(int) 构造函数
    return 0;
}

在这个例子中,MyClass(int)构造函数被声明为explicit,因此不能用于拷贝初始化。必须使用直接初始化的方式显式调用构造函数。

3. 防止隐式类型转换的链式调用

explicit可以防止多个隐式类型转换的链式调用,从而避免潜在的错误。

示例1:没有使用explicit

class MyClass {
public:
    MyClass(int x) : value(x) {} // 非explicit构造函数
    int value;
};

class YourClass {
public:
    YourClass(MyClass obj) : myObj(obj) {} // 非explicit构造函数
    MyClass myObj;
};

int main() {
    YourClass obj = 10; // 隐式调用 MyClass(int) 和 YourClass(MyClass)
    return 0;
}

在这个例子中,MyClass(int)YourClass(MyClass)构造函数都是非explicit的,因此可以隐式地将int类型转换为MyClass类型,再将MyClass类型转换为YourClass类型。

示例2:使用explicit

class MyClass {
public:
    explicit MyClass(int x) : value(x) {} // explicit构造函数
    int value;
};

class YourClass {
public:
    explicit YourClass(MyClass obj) : myObj(obj) {} // explicit构造函数
    MyClass myObj;
};

int main() {
    // YourClass obj = 10; // 错误:无法隐式调用 MyClass(int) 和 YourClass(MyClass)
    YourClass obj(MyClass(10)); // 显式调用 MyClass(10) 和 YourClass(MyClass)
    return 0;
}

在这个例子中,MyClass(int)YourClass(MyClass)构造函数都被声明为explicit,因此不能隐式地进行类型转换。必须显式地调用构造函数。

4. 防止隐式类型转换的歧义

在某些情况下,多个构造函数可能导致隐式类型转换的歧义。使用explicit可以避免这种歧义。

示例1:没有使用explicit

class MyClass {
public:
    MyClass(int x) : value(x) {} // 非explicit构造函数
    MyClass(double x) : value(static_cast<int>(x)) {} // 非explicit构造函数
    int value;
};

void printMyClass(MyClass obj) {
    std::cout << obj.value << std::endl;
}

int main() {
    printMyClass(10); // 隐式调用 MyClass(int) 构造函数
    printMyClass(10.5); // 隐式调用 MyClass(double) 构造函数
    return 0;
}

在这个例子中,MyClass(int)MyClass(double)构造函数都是非explicit的,因此可以隐式地将intdouble类型转换为MyClass类型。

示例2:使用explicit

class MyClass {
public:
    explicit MyClass(int x) : value(x) {} // explicit构造函数
    explicit MyClass(double x) : value(static_cast<int>(x)) {} // explicit构造函数
    int value;
};

void printMyClass(MyClass obj) {
    std::cout << obj.value << std::endl;
}

int main() {
    // printMyClass(10); // 错误:无法隐式调用 MyClass(int) 构造函数
    // printMyClass(10.5); // 错误:无法隐式调用 MyClass(double) 构造函数
    printMyClass(MyClass(10)); // 显式调用 MyClass(int) 构造函数
    printMyClass(MyClass(10.5)); // 显式调用 MyClass(double) 构造函数
    return 0;
}

在这个例子中,MyClass(int)MyClass(double)构造函数都被声明为explicit,因此不能隐式地进行类型转换。必须显式地调用构造函数,避免了潜在的歧义。

总结

explicit关键字的主要作用是防止隐式类型转换和拷贝初始化,从而提高代码的可读性和安全性。在设计类时,如果某个构造函数或转换运算符不应该被隐式调用,应该使用explicit关键字进行修饰。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。