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

时间:2017-09-20 17:33:49

标签: c++ cmake clion

我正在做一个关于C ++的教程,真正深入研究它的细节,因为坦率地说它是一种非常强大的语言。虽然我还是比较陌生,但是我的运算符重载为ostream运算符时遇到了问题。

由于这是一个教程,我试图尽可能保持我的代码有序和模块化,以避免混淆。我的代码有3层:

  • main.cpp - 运行练习。
  • Exercises.cpp / Exercises.h - 包含练习的静态函数。
  • ComplexNumber.cpp / ComplexNumber.h - 表示符合本教程的复数对象。

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;
}

头文件只有该函数的头部作为公共静态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

当我建立这个时,它告诉我,我有一个&#34;未定义的引用'cave_of_programming :: operator&lt;&lt;(std :: ostream&amp;,cave_of_programming :: ComplexNumber&amp;) &#39 ;.方法标题匹配,我与Jetbrains CLion建立。

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

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

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

1 个答案:

答案 0 :(得分:2)

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

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

在类中定义运算符,并仅将ostream作为参数

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

或者在类外部定义运算符并为其提供两个参数:

class ComplexNumber 
{
    ...
};

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

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

另请注意,在这里使用const是个好主意,就像我在示例中一样,否则你将无法在const ComplexNumbers上使用运算符。