iBug
iBug

Reputation: 37287

Strange behavior for overloaded I/O operator in class

I wrote a small music program on Windows for fun. I found the part of code going wrong. This is the minimized code (MCVE) for reproducing the problem:

#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);
}

And here's the running part:

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

Given the input 0 0, the output is supposed to be 0, but the actual output is ridiculously big (624). I tried this

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

And the output is 00 (no space between, see code), as expected.

Upvotes: 1

Views: 26

Answers (1)

M.M
M.M

Reputation: 141628

is >> k.p has special behaviour because k.p has character type. The input 0 will generate the character '0', not the value 0. In technical terms, the overload of std::istream::operator>> has this different behaviour when the right-hand argument has character type.

So input 0 0 on an ASCII system would generate output 48 * 12 + 48 which happens to be 624.

You probably want to read into an int variable and then convert to the range of k.p (with some error handling in case of out-of-range input).

Upvotes: 1

Related Questions