类中重载I / O运算符的奇怪行为

时间:2017-12-27 06:52:10

标签: c++ operator-overloading

我在Windows上写了一个小小的音乐节目以获得乐趣。我发现代码部分出错了。这是用于再现问题的最小化代码(MCVE):

#include <iostream>
using std::istream;
using std::cin;
using std::cout;
using std::cerr; // Debug output goes to stderr
using std::endl;

class Key {
    public:
    typedef signed char Pitch, Octave; // -128 to 127
    typedef signed long Absolute; // -2147M to 2147M
    Pitch p;
    Octave o;

    public:
    Key(const Pitch& _p, const Octave& _o) :
        p(_p), o(_o) {}
    Key(void) : Key(Pitch(0), Octave(0)) {};
    Absolute abs(void) const {
        return 12L * Absolute(o) + Absolute(p);
    }
    friend istream& operator>> (istream&, Key&);
};

istream& operator>> (istream& is, Key& k){
    return (is >> k.p >> k.o);
}

这是正在运行的部分:

Key k;
cin >> k;
cout << k.abs() << endl;

给定输入0 0,输出应该是0,但实际输出非常大(624)。我试过这个

cerr << k.p << k.o << endl;

输出为00(两者之间没有空格,请参阅代码),正如预期的那样。

1 个答案:

答案 0 :(得分:1)

is >> k.p具有特殊行为,因为k.p具有字符类型。输入0将生成字符'0',而不是值0。在技​​术术语中,当右侧参数具有字符类型时,std::istream::operator>>的重载具有这种不同的行为。

因此,ASCII系统上的输入0 0将生成恰好为48 * 12 + 48的输出624

您可能希望读入一个int变量,然后转换为k.p的范围(在超出范围的情况下进行一些错误处理)。