使用常量C字符串指针时构造函数编译错误咨询
问题根源:C++的「最令人头疼的解析(Most Vexing Parse)」
你遇到的这个差异,核心原因是C++编译器的函数声明解析优先级——这就是圈内大名鼎鼎的「最令人头疼的解析」问题,咱们一步步拆解:
为什么第一段代码能正常运行?
第一段代码:
T t1( T2( "TEST") ); t1.print();
这里的T2("TEST")里,"TEST"是字符串字面量,编译器没法把它解析成「函数参数的类型名」(字面量不能作为类型),所以只能把t1判定为T类型的对象,用T2临时对象来构造,自然能正常调用print()。
为什么第二段代码会报错?
第二段代码:
const char * TEST_STRING = "TEST"; T t1( T2( TEST_STRING ) ); t1.print(); // 报错:t1是函数类型,没有print成员
编译器会把T t1( T2( TEST_STRING ) );解析成一个函数声明,而不是对象定义:
- 它被理解为:声明了一个名为
t1的函数,返回值类型是T - 函数的参数是:一个名为
TEST_STRING、类型为T2的参数(在函数声明里,T2(TEST_STRING)等价于T2 TEST_STRING,参数名可以省略)
换句话说,编译器把t1当成了函数,而不是T类的对象,所以调用t1.print()时自然会报错——函数没有print成员方法。
解决办法(三种常用方案)
针对这种解析歧义,你可以用以下任意一种方式避免:
1. 使用C++11及以后的列表初始化语法
// 两种写法都可以 T t1{ T2(TEST_STRING) }; // 或者 T t1(T2{TEST_STRING});
列表初始化{}会强制编译器把它解析成对象构造,不会触发函数声明解析。
2. 给临时对象套额外的括号
T t1( (T2(TEST_STRING)) );
外层多一对括号后,编译器无法把它解析成函数声明,只能判定为对象构造。
3. 先显式创建T2对象,再构造T
T2 t2(TEST_STRING); T t1(t2);
这种写法最直观,完全避免了歧义。
内容的提问来源于stack exchange,提问作者Pittawat Pamornchasirikij
相关产品推荐
相关产品推荐

