【问题标题】:Function call priority in output stream输出流中的函数调用优先级
【发布时间】:2020-06-29 14:29:03
【问题描述】:

所以,我有以下课程:

typedef double decimal;

class Ratio {
  int num, den;
  decimal val;

public:
  Ratio() { num = 1, den = 1, val = (decimal)num / den; }

  Ratio update(int a, int b) {
    num *= a, den *= b;
    val = (decimal)num / den;
    return *this;
  }

  decimal v(void) { return val; }

  friend ostream &operator<<(ostream &out, const Ratio &R) {
    return (out << R.num << ':' << R.den);
  }
};

当我在输出流中使用成员函数时:

cout<<"R = "<<R.update(2,1)<<"\tvalue = "<<R.v();

其中 R 是 Ratio 类型,首先调用右端的函数,因此它显示更新的比率但未更新的值:

R = 2:1    value = 1

我通过将流分成两部分来克服这个问题:

cout<<"R = "<<R.update(2,1), cout<<"\tvalue = "<<R.v();

所以我“强制” .update() 首先被调用。是否有另一种方法来实现这一点,只使用一个流进行输出?

【问题讨论】:

  • 该代码是您正在处理的实际代码还是只是一个玩具示例?
  • 评估顺序已在c++17 中更新。使用该标准,您的代码将得到很好的定义。有关详细信息,请参阅cppreference
  • @super 啊,你是对的!不知何故我没有看到这一点(19)......我会更新我的答案。
  • @florestan 部分代码,省略了大部分与问题无关的代码

标签: c++ class stream member


【解决方案1】:

由于 c++ 中没有保证的评估顺序,因此如果不将其拆分为单独的部分,它将无法工作,就像您在修复中所做的那样。

引用cppreference

C++ 中没有从左到右或从右到左求值的概念。不要与运算符的从左到右和从右到左的结合性混淆:表达式 a() + b() + c() 被解析为 (a() + b()) + c( ) 由于 operator+ 的从左到右的关联性,但对 c 的函数调用可以在运行时首先、最后或在 a() 或 b() 之间进行评估

正如用户@super 所指出的,从 c++17 开始,移位运算符的求值顺序现已定义。它隐藏在我上面链接的页面上的规则的第 19 条)中。所以如果你能 c++17,你就完成了。

【讨论】:

  • 任何方式来指示编译器以何种顺序评估 的参数
【解决方案2】:

把值也放在

 friend ostream& operator<<(ostream &out,const Ratio &R){return (out<<"R = "<<R.num<<':'<<R.den<<"\tvalue = "<<R.val);}

现在

#include<iostream>

using namespace std;

typedef double decimal;

class Ratio{
    int num,den;
    decimal val;
public:
    Ratio(){num=1,den=1,val=(decimal)num/den;}
    Ratio update(int a,int b){
        num*=a,den*=b;
        val=(decimal)num/den;
        return *this;
    }
    friend ostream& operator<<(ostream &out,const Ratio &R){return (out<<"R = "<<R.num<<':'<<R.den<<"\tvalue = "<<R.val);}
};

int main()
{
    Ratio R;

    cout<<R.update(2,1)<<endl;

}

输出:

  R = 2:1 value = 2

  Process returned 0 (0x0)   execution time : 0.382 s
  Press any key to continue.

【讨论】:

  • 当然,这是一种方式,但我希望这两个东西在需要时单独打印,如果不需要单独调用,如图所示
猜你喜欢
  • 2021-08-10
  • 2014-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 2011-12-29
相关资源
最近更新 更多