c – 为什么没有为给定的转换操作符调用构造函数?

struct A {}; 
struct B
{
  B (A* pA) {}
  B& operator = (A* pA) { return *this; }
};

template<typename T>
struct Wrap
{
  T *x; 
  operator T* () { return x; }
};

int main ()
{
  Wrap<A> a;
  B oB = a; // error: conversion from ‘Wrap<A>’ to non-scalar type ‘B’ requested
  oB = a;  // ok
}

当构造oB时,为Wrap< T> ::运算符T()调用为什么B :: B(A *)? [注意:在下一个语句中为Wrap< T> :: operator T()调用B :: operator =(A *)]

解决方法

问题在于,隐式调用用户定义转换的数量受标准限制(为1).
B ob = a;

意味着两次用户转换:

> on a:Wrap< A> ::运算符A *()应该被调用
>结果:应该调用B :: B(A *)

@James Kanze的解释:这种语法称为“复制初始化”,实际上相当于B ob = B(a)(大部分时间都复制了副本).这与B ob(a)不同,后者是“直接初始化”并且可以工作.

如果您明确限定任何一项,它将起作用,例如:

B ob = B(a);

另一方面,对于第二种情况,没有问题:

ob = a;

是短手:

ob.operator=(a);

因此,只允许进行一次用户定义的转换.

编辑:

由于评论中需要(对基里尔的答案),我们可以猜测一下动机.

链式转换可能很长很长,因此:

>可能会让用户感到惊讶 – 隐含的转换可能已经令人惊讶,因为它……
>可以导致指数搜索可能性(对于编译器) – 它需要从两端开始,尝试检查所有可能的转换,并以某种方式“加入”两者(尽可能使用最短路径).

此外,只要转换次数超过1次,您就会遇到必须检测到周期的风险(即使可能不需要诊断,并且要遵守实施质量).

所以,因为有必要限制以避免无限长的搜索(它可能没有指定,只需要最少),并且因为超过1我们可能有新的问题(周期),那么1似乎是一个很好的限制,毕竟.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...