【问题标题】:Already defined error with operator overloading运算符重载已定义错误
【发布时间】:2015-11-20 20:04:53
【问题描述】:

在调试我的程序时,我不断收到以下两个错误:

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) 已在 Imaginary.obj 中定义

1>main.obj : error LNK2005: "class std::basic_ostream > & __cdecl operator &,class Complex const &)" (??6@YAAAV?$basic_ostream@DU ?$char_traits@D@std@@@std@@AAV01@ABVComplex@@@Z) 已经在 Imaginary.obj 中定义

我已尝试重新启动我的项目,以确保我创建了一个控制台应用程序,而不是意外创建了其他东西,但这并没有奏效。任何方向将不胜感激。

这是我的代码:

虚构的.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;
}

【问题讨论】:

  • 你的文件边界是什么? operator&lt;&lt;operator&gt;&gt; 定义是否在 header 中?
  • 请将代码分成文件并修复您的字符串文字(跨越多行)。
  • 变量ir 将只用imagreal 的未初始化值初始化一次。如果您想让ir 反映imagreal 的变化值,则必须在更新imagreal 时更新ir。那么,为什么要打扰副本呢?如果必须,您可以将ir 声明为imagr引用。但是然后问自己为什么需要副本?您是否正在尝试执行 gettersetter 功能?同样的原则适用于oop
  • 您需要在返回之前验证complex.o 变量。例如,您的代码允许这些输入作为有效条目:4M6i、4*6i、4@6i、4z6i。

标签: c++ class operator-overloading complex-numbers


【解决方案1】:

问题是你已经定义了

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.cppmain.cpp 中,所以它们被多次定义。这违反了single definition rule of C++

您需要将operator &lt;&lt;operator &gt;&gt; 的实现移动到.cpp 文件中,并且只将声明保留在头文件中。这意味着拥有

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

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

在头文件中定义类之后

class Complex {
    ...
};

在结尾 #endif 之前。然后在imaginary.cpp 中你会有定义

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

【讨论】:

  • 没有。包含守卫不会阻止多重定义。除非标记为inline(或static;ew),否则它们必须移至.cpp
  • 好的,所以我这样做了,但我仍然收到错误消息。它们现在还包括这个:致命错误 LNK1169:找到一个或多个多重定义的符号
  • @LightnessRacesinOrbit 这就是我要编辑的地方。
  • 您的编辑说这是一种替代方法。不,这是唯一的方法。
  • 呃 @LightnessRacesinOrbit 对不起,是的,一切都倒退了!我现在就修。
【解决方案2】:

您的错误在于您的标头保护:

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

当您在两个文件中包含头文件时,它们各自在各自的编译单元中编译函数。这就是链接时出错的原因。

您的文件应如下所示:

#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

还有两件事:

  1. 不应将函数定义放在标题中。你应该把它放在你的 cpp 文件中
  2. 除了标题保护之外,您还应该添加#pragma once。它应该在保持标准代码的同时防止一些错误。

【讨论】:

  • 没有。包含守卫不会阻止多个定义。
【解决方案3】:

你有两个选择:

  1. 将运算符方法的实现移动到单个 cpp 文件中
  2. 或者将实现声明为inline

例如,在你的头文件中,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.

或者您可以简单地将实现移动到您的 imaginary.cpp 文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-01
    • 2013-11-14
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 2015-07-04
    相关资源
    最近更新 更多