为什么转换函数在分配给对象时不用于该对象?

Why conversion function is not used for an object when it is assigned to?

提问人:Sam 提问时间:4/24/2023 最后编辑:user12002570Sam 更新时间:4/26/2023 访问量:1160

问:

我了解到我们可以在 C++ 中为我们的类提供转换运算符。所以我预计对于以下程序,将使用转换运算符。但令我惊讶的是;这不会发生,我们得到一个编译器错误,说c=1;int()

error: no match for 'operator=' (operand types are 'C' and 'int').

所以我想知道为什么这里不使用转换运算符。

struct C {
    explicit C(int);
    operator int&(); 
};

int main() {
    C c({});
    c = 1;   //this gives error. Why the conversion operator int&() is not used here?
}

请注意,我知道如果我只是从构造函数中删除关键字,我就可以解决错误。但我的问题是关于为什么不使用转换运算符。explicit

我认为,由于我们的类有一个转换运算符,因此可以将类对象转换为 以便可以将其分配给。int

C++ 类型转换 language-lawyer assignment-operator 显式

评论

5赞 Pete Becker 4/24/2023
转换运算符则反其道而行之:。int i = c;
1赞 Sam Varshavchik 4/24/2023
因为 C++ 不是这样工作的。 不会“转换为整数”。说完了,你仍然有一个剩余的,而不是一个整数。 C++对一切都有规则。如果你想让它以这种方式工作,那就是它的用途。 用于分配给类的实例。转换运算符用于类的实例进行赋值。c = 1Coperator=operator=
2赞 PaulMcKenzie 4/24/2023
@Sam我了解到我们可以在 C++ 中为我们的类提供转换运算符——这是一个基于意见的评论,但你学到了C++中最容易出错的方面之一。对于一个不平凡的程序,您能知道何时何地使用转换运算符吗?我敢打赌不会 -- 你没想到突然被调用的代码被调用了。这就是为什么标准库几乎不使用它的原因。例如,不重载是为 .c_str()const char *std::string
7赞 PaulMcKenzie 4/24/2023
@Sam -- 我建议谨慎使用转换运算符。不要让你的整个代码库都依赖于这些无声转换 - 从我这里拿走它,它可能会导致非常难以发现的错误。
1赞 Nicol Bolas 4/24/2023
@Sam:“我没有看到任何基于我的评论的意见。他说他自己的评论是基于意见的。

答:

13赞 user12002570 4/24/2023 #1

我认为,由于我们的类有一个转换运算符,因此可以将类对象转换为 int,以便将其分配给。

因为对于内置赋值运算符的左手操作数,不考虑用户定义的转换。这可以从表达式文档中的运算符中看出:

对于内置赋值运算符,左操作数的转换受到如下限制:

  • 没有引入临时操作数来保存左操作数,并且
  • 不会对左操作数应用任何用户定义的转换,以实现与内置候选项的最左侧参数的类型匹配。

(强调我的)

这意味着程序的格式不正确

评论

4赞 Artyer 4/24/2023
"x = y总是意味着如果 x 具有类类型“是我见过的最清晰的说法x.operator=(y)
3赞 user12002570 4/24/2023
@Artyer 是的,对于一个外行来说,这应该足够好了。只有当C++那么简单(或者有那么简单的措辞)时。
4赞 Karen Baghdasaryan 4/25/2023 #2

有关正式解释,请参阅此答案。我将尝试提供一种直觉,说明为什么这不能按照您的预期工作。 在你的问题中,你试着计算出以下表达式

c = 1;

其中 是 的实例。我们可以用两种方法来解决这个问题。cclass C

  • 使赋值运算符接受 type 的参数int
  • 使隐式构造函数接受 。int

因此,如果我们使用上述表达式,上面应该就足够了。

但是,人们可能想写这样的东西。

int i = c; // again, c is instance of C

我们(如果我们试着想想语言设计师可能是怎么想的)也需要解决这个问题。因此,为此目的的设计者决定制作一个转换运算符,这尤其适用于这种情况。

综上所述

  • 如果我们想从 中 ,我们定义一个构造函数,其接受ABAB
  • 如果我们也想从(我们不能或不想定义一个接受的构造函数),我们制作一个转换运算符,它按照我们的意愿转换为。BABAAB