3 回答
TA贡献2051条经验 获得超10个赞
如果它们是相关的
让我们暂时假设它B
实际上是一个基础D
。然后,对于调用check
,两个版本都是可行的,因为Host
可以转换为D*
和 B*
。它是用户定义的转换序列,分别由13.3.3.1.2
from 和Host<B, D>
to 描述。为了找到可以转换类的转换函数,根据第一函数合成以下候选函数D*
B*
check
13.3.1.5/1
D* (Host<B, D>&)
第一个转换函数不是候选函数,因为B*
无法转换为D*
。
对于第二个功能,存在以下候选者:
B* (Host<B, D> const&)D* (Host<B, D>&)
这些是获取主机对象的两个转换函数候选者。第一个是const引用,第二个不是。因此,第二个是非const *this
对象(隐含对象参数)的更好匹配,13.3.3.2/3b1sb4
并用于转换B*
为第二个check
函数。
如果你要删除 const,我们会有以下候选人
B* (Host<B, D>&)D* (Host<B, D>&)
这意味着我们不能再通过constness选择了。在普通的重载解析方案中,调用现在是不明确的,因为通常返回类型不会参与重载解析。但是,对于转换函数,有一个后门。如果两个转换函数同样好,那么它们的返回类型决定谁是最好的13.3.3/1
。因此,如果你想删除的常量,那么第一个将采取,因为B*
转换更好的B*
比D*
对B*
。
现在用户定义的转换顺序更好?第二次或第一次检查功能?规则是用户定义的转换序列只有在根据它们使用相同的转换函数或构造函数时才能进行比较13.3.3.2/3b2
。这就是这里的情况:两者都使用第二个转换函数。请注意,因此const很重要,因为它强制编译器采用第二个转换函数。
既然我们可以比较它们 - 哪一个更好?规则是从转换函数的返回类型到目标类型的更好转换(再次13.3.3.2/3b2
)。在这种情况下,D*
转换为to to D*
than B*
。因此选择了第一个函数,我们认识到了继承!
请注意,由于我们从未需要实际转换为基类,因此我们可以识别私有继承,因为我们是否可以从a转换D*
为a B*
不依赖于继承的形式根据4.10/3
如果他们没有关系
现在让我们假设它们与继承无关。因此,对于第一个功能,我们有以下候选人
D* (Host<B, D>&)
而对于第二个,我们现在有另一套
B* (Host<B, D> const&)
由于我们无法转换D*
为B*
如果我们没有继承关系,我们现在在两个用户定义的转换序列中没有共同的转换函数!因此,如果不是第一个函数是模板的事实,我们将是模棱两可的。当有一个同样好的非模板函数时,模板是第二选择13.3.3/1
。因此,我们选择非模板函数(第二个),我们认识到B
和之间没有继承D
!
TA贡献1776条经验 获得超12个赞
在你的第二个问题之后,请注意,如果它不是const,如果用B == D实例化,Host将是格式错误的。但is_base_of的设计使得每个类都是它自己的基础,因此转换运算符之一必须是const。
- 3 回答
- 0 关注
- 545 浏览
添加回答
举报