编译器如何知道为多态类型选择哪个函数?

时间:2017-01-11 16:19:23

标签: c++

例如,我以两种不同的方式重载operator<<

ofstream & operator<<(ofstream & fout, const Thing & t);

ostream & operator<<(ostream & out, const Thing & t);

我之所以这样做,是因为我希望文件的输出与输出到控制台的输出不同。据我所知,ofstream派生自ostream,因此编译器如何知道使用ofstream选择重载运算符而不是仅选择ostream的运算符当我做像

这样的事情
ofstream fout("file.txt")
fout.open();
Thing t;
fout << t;

因为即使没有使用ofstream的重载运算符,该代码仍然适用于ostream

3 个答案:

答案 0 :(得分:3)

通常,参数最接近参数的候选函数是被调用的候选函数。

它选择最接近的匹配,ofstream过载更接近,但如果不存在其他过载,则ostream有效。如果存在完全匹配,则可以使用它。

在重载开始之前,通过名称查找和模板参数推导选择的函数被组合起来形成一组候选函数(确切的标准取决于发生重载决策的上下文)

重载初始化考虑的参数 - 参数隐式转换序列对应于复制初始化中使用的隐式转换(对于非参考参数),除了考虑转换为隐式对象参数或赋值运算符的左侧时,不考虑创建临时对象的转换。 每种类型的标准转换序列都分配了三个等级中的一个:

  1. 完全匹配:无需转换,左值到右值转换, 资格转换,函数指针转换,(自C ++ 17起) 用户定义的类类型转换为同一个类

  2. 促销:整体推广,浮点促销

  3. 转换:积分转换,浮点转换, 浮点积分转换,指针转换,指向成员的指针 转换,布尔转换,派生的用户定义转换 等级到它的基础

  4. 标准转换序列的排名是其持有的标准转化次数中最差的(最多可能有三次转化)

答案 1 :(得分:0)

重载分辨率始终优先选择完全匹配。由于std::ofstream完全匹配,请参阅this以获取有关重载决策的更多信息。 std::ostream也匹配,但优先级较低。如果删除所有其他更高优先级的重载,将使用它,例如,如果消除std::ofstream重载。

答案 2 :(得分:0)

ofstream来自ostream。所以,

  • ofstream对象将在<{1}}对象可接受的地方使用。否则,

  • 只要ofstream对象可以接受,
  • ofstream对象就可以使用。

C ++规范N3690 参考绑定

  

当引用类型的参数直接绑定(8.5.3)为a时   参数表达式,隐式转换序列是标识   转换,除非参数表达式的类型是a   派生类的参数类型,在这种情况下是隐式的   转换序列是派生到基础的转换(13.3.3.1)。

ostream

简单来说:

  • 参数有 类类型和参数表达式具有相同的类型,隐式转换序列是标识转换。

  • 当参数具有类类型且参数表达式具有派生的类类型时,隐式转换序列是从派生到基础的转换派生类到基类。