Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
242 views
in Technique[技术] by (71.8m points)

c++ - No operator ">>" matches these operands operand types are: std::istream >> double

For my project I'm trying to create a free function for a complex number class. It is defined in the cpp file. The function is an overloaded input streaming operator but I keep getting the error

No operator ">>" matches these operands operand types are: std::istream >> double

on the lines

in >> z.real();
in >> z.imag();

I made a file called complex.h that contains the complex class and the two overloaded operators I want to work, constructors for complex numbers (not sure if needed but included), and two getter methods to retrieve the real and imaginary parts of the complex class. This reproduces the error.

The declarations of the member functions are dictated by my project spec. Their return types cannot be changed.

#pragma once
#include <iostream>
#include <cmath>

class complex {

private://may include private helper functions
    double realX = 0;
    double imaginaryY = 0;

public:// interface for operators and member functions (methods)
    //**********************Constructors***************************
    complex() {}
    complex(double x) {
        realX = x;
    }
    complex(double x, double y) {
        realX = x;
        imaginaryY = y;
    }
    complex(const complex& z) : realX(z.realX), imaginaryY(z.imaginaryY) { //copy constructor
    }
    double real() const {
        return realX;
    }
    double imag() const {
        return imaginaryY;
    }
};

std::istream& operator>>(std::istream& in, complex& z) {
    in >> z.real();
    in >> z.imag();
    return in;
}
std::ostream& operator<<(std::ostream& output, const complex& z) {
    output << "(" << z.real()
        << ", " << z.imag()
        << "i)";
    return output;
}

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
No operator ">>" matches these operands operand types are: std::istream >> double

This might seem like a strange error message. After all, one could fairly quickly come up with an example program that streams a double from std::cin, which is a std::istream. So what is wrong here?

The answer comes in that mess of notes that follows this error message. (Yes, it can be an intimidating mess, but the notes are there to help diagnosing the problem. No, I do not expect the entire mess to be copied into the question, since it is large and most of it is not relevant.) Somewhere in the list of candidate operators is

operator>>(double& __f)

This is the operator that allows streaming a double. However, note the type of the parameter – it is not double, but double&. The target of the stream must name a variable, not merely provide a value. In your case, attempting in >> z.real() is similar to attempting in >> 3.1. The types of z.real() and 3.1 are both double, so what you can do to one you can do to the other. Hopefully you do not believe you can change mathematics by streaming a new value into 3.1. Similarly, you cannot stream a value into a function that returns a double.

One solution is to make your function return what the stream operator expects, as in double& real() (add an ampersand and remove const). However, providing a public non-const reference to a private member destroys encapsulation; the member might as well be public at that point. Plus, your project does not allow it. Let's look for a better approach.

A more common solution is to make operator>> a friend of your class so that it can set the private members. This requires adding the line

friend std::istream& operator>>(std::istream& in, complex& z);

to your class definition. After that is done, your implementation of operator>> can access the private data members, bypassing the accessor functions. Note: the definition of operator>> can stay right where it is, outside the class definition, if that is desirable.

std::istream& operator>>(std::istream& in, complex& z) {
    in >> z.realX;
    in >> z.imaginaryY;
    return in;
}

A more roundabout approach uses construction and assignment instead of friendship. This might reduce code duplication in more complex cases. However, in your case it triggers a warning because your class violates the Rule of Three by having a copy constructor but no assignment operator. Still, your explicit copy constructor is what the compiler would automatically generate for you. You could address the warning by commenting out your copy constructor.

std::istream& operator>>(std::istream& in, complex& z) {
    double real;
    double imaginary;
    
    in >> real;
    in >> imaginary;
    z = complex{real, imaginary};
    
    return in;
}

For something as simple as your complex class, I would go with friendship.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...