C++ Ostream 运算符重载 - 构建时奇怪的未定义引用

C++ Ostream Operator Overload - odd undefined reference when building

我正在编写有关 C++ 的教程,以真正深入研究它的 nitty-gritty,因为坦率地说,它是一种很棒且功能强大的语言。不过,我对它还是很陌生,我在为 ostream 运算符重载运算符时遇到了问题。

因为这是一个教程,所以我尽量使我的代码井井有条和模块化,以避免混淆。我的代码有 3 层:

Main 相当简单:一组对 Exercises::ExerciseName() 的调用。

Exercises.cpp:

#include "Exercises.h"
void Exercises::ComplexNumberClass() {
    ComplexNumber c;    /** Runs the blank constructor  */
    ComplexNumber c1(2, 3); /** Runs the args-filled constructor    */
    ComplexNumber c2 = c1;  /** Runs the copy constructor   */

    c = c2;

    cout << c1 << endl;
}

header 文件只有 header 作为 public static void 函数,即可调用和可执行函数。 ComplexNumber 文件是我认为的问题所在(如果我错了请纠正我):

ComplexNumber.cpp(没有构造函数和访问器):

#include "ComplexNumber.h"

using namespace ComplexNumbers;
using namespace std;

ostream& operator<< (ostream& out, ComplexNumber& num){
    out << "(" << num.GetReal() << ", " << num.GetImaginary() << ")";
    return out;
}

const ComplexNumber &ComplexNumber::operator=(const ComplexNumber &num) {
    cout << "Using assignment operator override" << endl;

    real = num.real;
    imaginary = num.imaginary;

    return *this;
}

ComplexNumber.h:

#ifndef OPERATOROVERLOADING_COMPLEXNUMBER_H
#define OPERATOROVERLOADING_COMPLEXNUMBER_H

#include <iostream>

using namespace std;

namespace ComplexNumbers {
    class ComplexNumber {
    private:
        double real;
        double imaginary;

    public:
        ComplexNumber();

        ComplexNumber(double real, double imaginary);

        ComplexNumber(const ComplexNumber &num);

        const ComplexNumber &operator=(const ComplexNumber &num);

        double GetReal() const {
            return real;
        }

        double GetImaginary() const {
            return imaginary;
        }
    };

    ostream &operator<<(ostream& out, ComplexNumber& num);
}

#endif //OPERATOROVERLOADING_COMPLEXNUMBER_H

当我构建它时,它告诉我我有一个“对 'cave_of_programming::operator<<(std::ostream&, cave_of_programming::ComplexNumber&)' 的未定义引用。方法 headers 匹配,我正在使用 Jetbrains CLion 构建。

我的研究表明问题出在链接器上,但我查看了我的 CMakeLists.txt 并发现它正在链接所有相应的文件。

SOURCE_FILES main.cpp Exercises.cpp Exercises.h ComplexNumbers/ComplexNumber.cpp ComplexNumbers/ComplexNumber.h

有人知道为什么这不起作用吗?我错过了什么?

问题是您在 class 中定义了 ostream &operator<<(ostream& out, ComplexNumber& num)。这对编译器没有多大意义,因为它知道在获取 ostream 对象和某种类型的 class 时覆盖 operator<<, 但是你实现它的方式,它得到了 ostream、一个 ComplexNumber 和另一个 ComplexNumber 作为 'this' 参考。

为了正确重载二元运算符,您有两个选择:

在class中定义运算符,只给它ostream作为参数

class ComplexNumber 
{
    ...
    ostream &operator<<(ostream& out) const;
};

或者在class之外定义运算符,并给它两个参数:

class ComplexNumber 
{
    ...
};

ostream &operator<<(ostream& out, const ComplexNumber& num);

请注意,在第二个实现中,如果要访问任何私有成员,则需要将函数添加为 class 的友元。

另请注意,最好像我在示例中那样在此处使用 const,否则您将无法在 const ComplexNumbers 上使用运算符。