如何定义支持参数隐式类型转换的构造函数?C++技术咨询
嘿,作为C++新手遇到这种隐式转换的问题太正常了,我来一步步帮你捋明白~
一、std::filesystem::path是怎么支持const char*隐式转换的?
你猜的完全没错,std::filesystem::exists能直接接收"/abc"这种字符串字面量,就是因为std::filesystem::path提供了非explicit的构造函数来支持隐式转换。
具体来说,C++17标准中std::filesystem::path有这样一个核心构造函数(简化版):
namespace std::filesystem { class path { public: // 没有加explicit,允许编译器自动隐式转换 path(const char* s); // ...其他构造函数 }; }
因为这个构造函数没有explicit关键字,当你把const char*类型的参数(比如字符串字面量退化成的const char*)传给需要path类型参数的函数时,编译器会自动调用这个构造函数,把const char*隐式转换成path对象——这就是std::filesystem::exists("/abc")能正常运行的核心原因。
二、你的自定义类代码为什么报错?怎么修改?
你的代码有两个关键问题,咱们一个个拆解:
问题1:构造函数的参数类型不匹配
你写的构造函数是:
A(const char*& msg)
这里的参数是**const char*的非const左值引用**,而字符串字面量"123"是const char[4]类型,会退化成const char*的右值。C++里右值是不能绑定到非const的左值引用上的,这就导致编译器找不到合适的构造函数来转换"123"。
问题2:构造函数的访问权限是private
在C++的class中,成员默认是private权限的,你的A类构造函数没有加public修饰,外部代码(比如main里的func)根本无法调用这个构造函数,这也是报错的重要原因。
修正后的代码
把这两个问题解决掉,代码就能正常运行了:
#include <iostream> class A { public: // 把构造函数设为public权限 // 改成const左值引用,或者直接用值传递const char* A(const char* const& msg) { std::cout << msg << std::endl; } // 或者更简单的写法,直接用值传递: // A(const char* msg) { // std::cout << msg << std::endl; // } }; void func(const A& p) {} int main(int argc, const char * argv[]) { func("123"); // 现在可以正常编译运行了 return 0; }
三、怎么编写支持隐式转换的自定义构造函数?
总结一下,要让你的类支持从某类型到自身的隐式转换,需要满足这几点:
- 构造函数不能加
explicit关键字(加了explicit就只能显式转换,无法隐式触发) - 构造函数的参数类型要能匹配你想转换的类型(比如要支持
const char*转换,参数得是const char*或者能接受它的const引用) - 构造函数的访问权限是
public(外部代码能调用到它)
内容的提问来源于stack exchange,提问作者Daiwei

