0

When i try to overload the "<<" operator in my .h file, i get the following error:

multiple definition of `operator<<(std::ostream&, complex_number&)' 

But when i move my operator overloading in my .cpp file, everything works just fine. I don't really know what is happening. Any help?

Here is my initial code:

(main.cpp is really simple and does not contain anything important)

complex_number.h

#ifndef COMPLEX_NUMBER_H
#define COMPLEX_NUMBER_H

#include <iostream>

using namespace std;


class complex_number
{
    public:
        complex_number();
        complex_number(double, double);
        virtual ~complex_number();

        double Geta() const { return a; }
        void Seta(double val) { a = val; }
        double Getb() const { return b; }
        void Setb(double val) { b = val; }

        void print();

        friend ostream & operator << (ostream &out, complex_number &cmp);

    protected:

    private:
        double a;
        double b;

};

ostream & operator << (ostream &out, complex_number &cmp) {
    double a = cmp.Geta();
    double b = cmp.Getb();
    if (a == 0 && b == 0){
        out << "0";
    }
    else if (a == 0) {
        //if (b < 0) cout << "-";
        if   (b == -1) {
            out << "-i";
        }
        if (b!=1) cout << b;
        out << "i";
    }
    else if (b == 0) {
        out << a;
    } else {
        out << a;
        out << (b > 0 ? "+" : "-");
        if (b!=1 && b!=-1) out << (b > 0 ? b : -1*b);
        out << "i";
    }

    return out;

}


#endif // COMPLEX_NUMBER_H

complex_number.cpp

#include "complex_number.h"
#include <iostream>
#include <string>

using namespace std;

complex_number::complex_number()
{
    //ctor
    a = 0;
    b = 0;
}

complex_number::complex_number(double a1, double b1)
{
    //ctor
    a = a1;
    b = b1;
}

void complex_number::print() {

    if (a == 0 && b == 0){
        cout << "0";
        return;
    }
    else if (a == 0) {
        //if (b < 0) cout << "-";
        if   (b == -1) {
            cout << "-i";
            return;
        }
        if (b!=1) cout << b;
        cout << "i";
        return;
    }
    else if (b == 0) {
        cout << a;
        return;
    }

    cout << a;
    cout << (b > 0 ? "+" : "-");
    if (b!=1) cout << (b > 0 ? b : -1*b);
    cout << "i";
    return;


}

complex_number::~complex_number()
{
    //dtor
}
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
petrosg
  • 89
  • 1
  • 7
  • 1
    Does this anwser your question? https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading – SzymonO May 27 '20 at 10:28
  • What has C got to do with your question? Please do not use unnecessary tags. – Paul Ogilvie May 27 '20 at 10:34
  • @SzymonO thanks for the useful material. Although, it does not specify the reason i can not place my operator overload code inside my .hfile – petrosg May 27 '20 at 10:36
  • `*.h` header files are for declarations. `*.cpp` source files are for definitions (and local declarations). When you put definitions in a header file, you'll run into these kinds of problems. – Eljay May 27 '20 at 11:14

1 Answers1

1

Because your .h file is included from multiple .cpp files, and each .cpp file is compiled separately as different compile units, and then linked together, thus, your << operator function will be in each of the compile units, and they conflict each other during link stage.

There are two options if you insist to leave it in the .h file.

option 1:

inline the << operator, inline functions will be expanded like macros, there will be no symbol generated for the function, thus, no conflicts:

inline ostream & operator << (ostream &out, complex_number &cmp) {

option 2:

make the << operator to be a static function. But you need to declare the function as static prior to declaring it as a friend.

The reason is that: Quoting N3691 - §11.3/4 [class.friend]

A function first declared in a friend declaration has external linkage (3.5). Otherwise, the function retains its previous linkage (7.1.1).

complex_number.h

class complex_number;
static ostream & operator << (ostream &out, complex_number &cmp);

class complex_number
{
    public:
        complex_number();
        complex_number(double, double);
        virtual ~complex_number();

        double Geta() const { return a; }
        void Seta(double val) { a = val; }
        double Getb() const { return b; }
        void Setb(double val) { b = val; }

        void print();

        friend ostream & operator << (ostream &out, complex_number &cmp);

    protected:

    private:
        double a;
        double b;

};

static ostream & operator << (ostream &out, complex_number &cmp) {
    double a = cmp.Geta();
   ....
}
Tiger Yu
  • 744
  • 3
  • 5