C++ Primer 第五版习题7-39:构造函数默认参数合法性咨询
C++ Primer 第五版习题7-39问题解答
问题背景
- 习题关联的
Sales_data类初始定义如下:
class Sales_data { public: // defines the default constructor as well as one that takes a string argument Sales_data(std::string s = ""): bookNo(s) {} // remaining constructors unchanged Sales_data(std::string s, unsigned cnt, double rev): bookNo(s), units_sold(cnt), revenue(rev*cnt) {} Sales_data(std::istream &is) { read(is, *this); } // remaining members as before };
- 习题核心问题:接收
std::string的构造函数与接收std::istream&的构造函数能否同时设置默认参数?若不合法请说明原因。
你的实现思路
你认为单个构造函数加默认参数语法合法,想按如下方式定义:
Sales_data(std::string s = ""): bookNo(s) {} Sales_data(std::istream &is = std::cin) { read(is, *this); }
核心问题说明
单独看每个构造函数的声明,语法上确实是合法的:给std::string类型参数设置默认值""符合规则,给std::istream&左值引用参数设置默认实参std::cin也没有语法错误。
但两个构造函数同时按上述方式定义在类中时,会触发重载二义性,这是代码不合法的根本原因:
- 当你定义不需要传入任何实参的
Sales_data对象时,例如写Sales_data obj;,两个构造函数都是可行的匹配项:- 第一个构造函数可以用默认实参
""匹配0个实参的调用 - 第二个构造函数可以用默认实参
std::cin匹配0个实参的调用
- 第一个构造函数可以用默认实参
- 根据C++重载决议规则,这两个可行函数的匹配优先级完全相等,编译器无法选出最优匹配,会直接报二义性错误,导致编译失败。
如果要让两个构造函数都保留默认参数且不冲突,只能做二选一的修改:要么删除其中一个构造函数的默认参数,让其无法作为默认构造函数使用;要么重构构造函数的参数列表,避免无实参调用时出现多个可行匹配。
内容的提问来源于stack exchange,提问作者yapkm01
相关产品推荐
相关产品推荐

