Brian Roper
Brian Roper

Reputation: 538

Already defined error with operator overloading

When debugging my program I keep getting these two errors:

main.obj : error LNK2005: "class std::basic_istream > & __cdecl operator>>(class std::basic_istream > &,class Complex &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAVComplex@@@Z) already defined in Imaginary.obj

1>main.obj : error LNK2005: "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class Complex const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVComplex@@@Z) already defined in Imaginary.obj

I have tried restarting my project to make sure that I created a console application and not something else on accident but that didn't work. Any direction would be greatly appreciated.

Here's my code:

imaginary.h

#ifndef imaginary_h_
#define imaginary_h_

#include <iostream>

class Complex
{    
    friend std::ostream & operator << (std::ostream& os, const Complex&);
    friend std::istream & operator >> (std::istream& is, Complex&);

private:    
    double real;
    double imag;
    char op;

public:    
    double r = real;
    double i = imag;
    char o = op;

    Complex()
    {    
    }

    Complex(double r, double i, char o)
    {    
    }

    bool userTest();    
};

#endif

std::ostream & operator << (std::ostream & os, const Complex & complex)    
{
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

std::istream & operator >> (std::istream & is, Complex & complex)    
{
    is >> complex.r >> complex.o >> complex.i;
    return is;
}

Imaginary.cpp

#include "imaginary.h"    
#include <iostream>

bool Complex::userTest()

{
    if (op == '+' || op == '-')

    {
        return true;
    }

    else

    {
        std::cout << "Incorrect operand entry, please enter complex number as x+yi" << "/n" << "/n";

                return false;
    }

}

main.cpp

#include "imaginary.h"

#include <iostream>


int main()
{
    double userInput;

    std::cout << "Here you will add or subtract complex numbers." << "/n" << "/n";

    do

    {

        std::cout << "Please enter the real part of you complex number: " << "/n" << "/n";

                Complex complex;

        std::cin >> complex;

        std::cout << "/n" << "/n" << "/n/t" << "Note: Remember to enter your complex number in the format of x+yi to avoid an error";

                if (complex.userTest())
                {
                    std::cout << complex << "/n" << "/n";
                }

        std::cout << "Would you like to perform another complex number operation? " << "/n" << "/n/t";

                        std::cout << "Choose 1 for Yes and 2 for No" << "/n" << "/n";

        std::cin >> userInput;

    } while (userInput == 1);

    system("pause");

    return 0;
}

Upvotes: 6

Views: 7913

Answers (3)

Thomas Matthews
Thomas Matthews

Reputation: 57678

You have two options:

  1. Move implementation of operator methods to a single cpp file
  2. Or declare the implementations as inline.

For example, in your header file, imaginary.hpp:

inline // <-- Add this line 
std::ostream & operator << (std::ostream & os, const Complex & complex)    
{
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

inline  // <-- Add this line 
std::istream & operator >> (std::istream & is, Complex & complex)    
{
    is >> complex.r >> complex.o >> complex.i;
    return is;
}

#endif  // imaginary_h_  <-- This line was moved.

Or you can simply move the implementations into your imaginary.cpp file.

Upvotes: 15

IKavanagh
IKavanagh

Reputation: 6187

The problem is that you have defined

std::ostream & operator<<(std::ostream &os, const Complex &complex) {
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

std::istream & operator>>(std::istream &is, Complex &complex) {
    is >> complex.r >> complex.o >> complex.i;
    return is;
}

in your header file and because this is included in imaginary.cpp and main.cpp they are defined multiple times. This violates the single definition rule of C++.

You need to move the implementation of operator << and operator >> to the .cpp file and only leave the declaration in the header file. This would mean having

std::ostream & operator<<(std::ostream &os, const Complex &complex);

std::istream & operator>>(std::istream &is, Complex &complex);

in the header file after the definition of the class

class Complex {
    ...
};

and before the ending #endif. Then in imaginary.cpp you would have the definition

std::ostream & operator<<(std::ostream &os, const Complex &complex) {
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

std::istream & operator>>(std::istream &is, Complex &complex) {
    is >> complex.r >> complex.o >> complex.i;
    return is;
}

Upvotes: 8

Guillaume Racicot
Guillaume Racicot

Reputation: 41760

Your error lies in your header guard:

    bool userTest();    
};

#endif // Here!

std::ostream & operator << (std::ostream & os, const Complex & complex)    
{
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

When you include the header in your two file, they each compile the function in their respective compilation unit. That's why there's an error at link time.

Your file should look like this:

#ifndef imaginary_h_
#define imaginary_h_

#include <iostream>

class Complex
{    
    friend std::ostream & operator << (std::ostream& os, const Complex&);
    friend std::istream & operator >> (std::istream& is, Complex&);

private:    
    double real;
    double imag;
    char op;

public:    
    double r = real;
    double i = imag;
    char o = op;

    Complex()
    {    
    }

    Complex(double r, double i, char o)
    {    
    }

    bool userTest();    
};

std::ostream & operator << (std::ostream & os, const Complex & complex)    
{
    os << complex.r << complex.o << complex.i << "i" << "/n" << "/n";
    return os;
}

std::istream & operator >> (std::istream & is, Complex & complex)    
{
    is >> complex.r >> complex.o >> complex.i;
    return is;
}

#endif

But two other things:

  1. You should not put function definition in you header. You should put it in your cpp file
  2. You should seek to add #pragma once in addition of your header guard. It should prevent some error while keeping a standard code.

Upvotes: -1

Related Questions