gpt4 book ai didi

C++:强制编译器使用两个竞争运算符之一

转载 作者:行者123 更新时间:2023-11-28 03:02:58 24 4
gpt4 key购买 nike

我最近一直在玩 C++,我偶然发现了一个有趣的优先级问题。我有一节课有两个运算符:“强制转换为 double ”和“+”。像这样:

class Weight {
double value_;
public:
explicit Weight(double value) : value_(value) {}
operator double() const { return value_; }
Weight operator+(const Weight& other) { return Weight(value_ + other.value_); }
};

当我尝试添加此类的两个实例时...

class Weighted {
Weight weight_;
public:
Weighted(const Weight& weight) : weight_(weight) {}
virtual Weighted twice() const {
Weight w = weight_ + weight_;
return Weighted(w);
}
};

...意外发生:编译器看到“+”号并将两个 weight_ 转换为 double。然后它吐出一个编译错误,因为由于我的 explicit 单参数构造函数,它不能隐式地将生成的 double 转换回 Weight 对象。

问题:我如何告诉编译器使用我自己的 Weight::operator+ 来添加两个对象,并忽略此表达式的转换运算符?最好不要调用 weight_.operator+(weight_),这会违背目的。


更新:非常感谢 chris 指出编译器不使用我类的 operator+ 是正确的,因为该运算符不是 const+ed 的对象是 const

我现在知道在 VS2012 中修复上述问题的三种方法。请查看克里斯接受的答案以获取更多信息。

  1. explicit 限定符添加到 Weight::operator double()。这在 VS 2012 中不起作用(不支持),但按理说对于接受这种方法(来自接受的答案)的编译器来说,这是一个很好的解决方案。
  2. 从方法 Weighted::twice 中删除 virtual 限定符,但不要问我为什么这在 VS 中有效。
  3. const 限定符添加到方法 Weight::operator+(来自接受的答案)。

最佳答案

当前版本:

首先,virtual 应该与它无关。我敢打赌这是 MSVC 的问题,特别是考虑到 Clang 没有区别。无论如何,您的 twice 函数被标记为 const。这意味着成员将是 const Weight 而不是 Weight。这是 operator+ 的问题,因为它只接受非常量 this。因此,编译器唯一的办法就是将它们转换为 double 并添加它们。

另一个问题是添加 explicit 会导致编译。事实上,这应该删除编译器转换为double 的最后手段。这确实是 Clang 上发生的事情:

error: invalid operands to binary expression ('const Weight' and 'const Weight')
Weight w = weight_ + weight_;
note: candidate function not viable: 'this' argument has type 'const Weight', but method is not marked const

最后,使 operator+ const(或自由函数)是正确的解决方案。当你这样做时,你可能认为你会加回这条路线,因此由于这条路线和 double 路线之间的歧义而产生另一个错误,但是 Weightconst Weight & 是标准转换,而 Weightdouble 是用户定义的转换,因此使用标准转换,一切正常。


作为问题中更新的代码,这很好。它无法编译的原因是 MSVC 的错误。作为引用,它does compile在 Clang 上。它还在 MSVC12 和 2013 CTP 上编译。


您可能将结果存储在 Foo 中,但仍然需要从 doubleFoo 的隐式转换。您应该在加法运算符中返回 Foo(value_ + other.value_) 以便转换是显式的。我建议让运算符(operator)也成为免费功能,因为免费运算符(operator)(几乎)总是至少和成员一样好。当我这样做时,构造函数初始化列表也是一个受欢迎的更改。

此外,从 C++11 开始,通常首选的选择是显式转换运算符:

explicit operator double() const {return value_;}

还要注意添加的const,因为没有状态被改变。

关于C++:强制编译器使用两个竞争运算符之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20308234/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com