Перегрузка оператора << в файлах .h - PullRequest
0 голосов
/ 27 мая 2020

Когда я пытаюсь перегрузить оператор «<<» в моем файле .h, я получаю следующую ошибку: </p>

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

Но когда я перемещаю перегрузку оператора в свой файл. cpp, все работает нормально. Я действительно не знаю, что происходит. Любая помощь?

Вот мой исходный код:

(main. cpp действительно прост и не содержит ничего важного)

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

комплексное_число. 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
}

1 Ответ

1 голос
/ 27 мая 2020

Поскольку ваш файл .h включен из нескольких файлов. cpp, и каждый файл. cpp компилируется отдельно как разные единицы компиляции, а затем связывается вместе, таким образом, ваша функция оператора << будет в каждом из модули компиляции, и они конфликтуют друг с другом на этапе компоновки. </p>

Есть два варианта, если вы настаиваете оставить его в файле .h.

вариант 1:

встроить оператор <<, встроенные функции будут расширены как макросы, для функции не будет генерироваться символ, следовательно, никаких конфликтов: </p>

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

вариант 2:

сделать < Оператор <как статическая c функция. Но вам нужно объявить функцию как stati c, прежде чем объявлять ее как друга. </p>

Причина в том, что: Цитата N3691 - §11.3 / 4 [class.friend]

A функция, впервые объявленная в объявлении друга, имеет внешнюю связь (3.5). В противном случае функция сохраняет свою предыдущую привязку (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();
   ....
}
...