微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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似乎是一个很好的限制,毕竟.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐