C++, good old LNK1169 (and LNK2005) errors

2019-01-29 02:51发布

问题:

I have 4 files, 2 headers and 2 cpp files.

Header file one:

#ifndef complex_2
#define complex_2
#include<iostream>
#include<cmath>

using namespace std;

namespace comp
{
    class complex{
    protected:
        double re, im;
    public:
        complex(){re = im = 0;}
        complex(double re_in, double im_in){
            re = re_in;
            im = im_in;
        }
        ~complex(){}

        void set_re(double re_in){
            re = re_in;
        }
        void set_im(double im_in){
            im = im_in;
        }
        double get_re() const{
            return re;
        }
        double get_im() const{
            return im;
        }

        complex comp_conj() const{
            complex temp;
            temp.set_re(re);
            temp.set_im(-im);
            return temp;
        }

        complex operator + (const complex &c)const{
            complex temp(re + c.get_re(), im + c.get_im());
            return temp;
        }

        complex operator - (const complex &c)const{
            complex temp(re - c.get_re(), im - c.get_im());
            return temp;
        }

        complex operator * (const complex &c1)const{
            complex temp;
            double a(re), b(im), c(c1.get_re()), d(c1.get_im());
            temp.set_re(a*c - b*d);
            temp.set_im(b*c + a*d);
            return temp;
        }

        complex operator / (const complex &c1)const{
            complex temp;
            double a(re), b(im), c(c1.get_re()), d(c1.get_im());
            temp.set_re((a*c + b*d)/(pow(c,2) + pow(d,2)));
            temp.set_im((b*d - a*d)/(pow(c,2) + pow(d,2)));
            return temp;
        }

        double mod() const{
            return(sqrt(pow(re,2) + pow(im,2)));
        }

        double arg() const{
            return(atan(im/re));
        }

        friend ostream & operator << (ostream &mm, const complex &c);
    };
ostream & comp::operator<< (ostream &mm, const complex &c){
    if(c.get_im() >= 0){
        mm << "(" << c.get_re() << " + " << c.get_im() << "i)" << endl;
    }
    if(c.get_im() < 0){
        mm << "(" << c.get_re() << " - " << -(c.get_im()) << "i)" << endl;
    }
    return mm;
}
}
#endif

Header file 2:

#ifndef AC_Circuits_Header
#define AC_Circuits_Header
#include "Complex and Definitions.h"
#include<fstream>
#include<vector>
#include<string>

using namespace std;
using namespace comp;

class component{
public:
    virtual ~component(){}
    virtual void set_f(double m){}
    virtual double get_f() = 0;

    virtual complex impedance() = 0;
    virtual double reactance() = 0;
    virtual double phase_diff() = 0;
};

class resistor : public component{
protected:
    double R;
    bool para_or_series;
public:
    resistor(){R = para_or_series = 0;}
    resistor(double r_in, bool a){
        R = r_in;
        para_or_series = a;
    }
    ~resistor(){}

    double get_R(){return R;}
    void set_f(double m){}
    double get_f(){return 0;}

    complex impedance(){
        complex Z_R(R, 0);
        return Z_R;
    }

    double reactance(){return 0;}
    double phase_diff(){return 0;}
};

class capacitor : public component{
protected:
    double C, f;
    bool para_or_serie;
public:
    capacitor(){C = para_or_serie = 0;}
    capacitor(double c_in, bool a){
        C = c_in;
        para_or_serie = a;
    }
    ~capacitor(){}

    double get_C(){return C;}
    void set_f(double freq){f = freq;}
    double get_f(){return f;}

    complex impedance(){
        complex Z_C(0, (pow((2 * 3.14 * f * C), -1)));
        return Z_C;
    }

    double reactance(){
        return (-(pow((2 * 3.14 * f * C), -1)));
    }

    double phase_diff(){
        complex Z_C(0, (pow((2 * 3.14 * f * C), -1)));
        return Z_C.arg();   
    }
};

class inductor : public component{
protected:
    double L, f;
    bool para_or_series;
public:
    inductor() : L(0), para_or_series(0) {}
    inductor(double l_in, bool a) : L(l_in), para_or_series(a) {}
    ~inductor(){}

    double get_R(){return 0;}
    double get_C(){return 0;}
    void set_f(double b){f = b;}
    double get_f(){return f;}

    double reactance(){
        return (2 * 3.14 * f * L);  
    }

    complex impedance(){
        complex Z_L(0, (2 * 3.14 * f * L));
        return Z_L;
    }

    double phase_diff(){
        complex Z_L(0, (2 * 3.14 * f * L));
        return Z_L.arg();
    }
};

class circuit : public resistor, public capacitor, public inductor{
protected:
    complex Z_tot;
public:
    circuit() : Z_tot(0,0) {}
    circuit(bool a, resistor &R, capacitor &C, inductor &L){
        if(a == 1){
            Z_tot = R.impedance() + C.impedance() + L.impedance();
        }
        if(a == 0){
            complex one(1,0);
            Z_tot = one/(one/R.impedance() + one/C.impedance() + one/L.impedance());
        }
    }
    ~circuit(){}

    void set_f(){}
    double get_f(){return 0;}

    complex impedance(){}
    double reactance(){return 0;}
    double phase_diff(){return 0;}
};
#endif

cpp file one:

#include "AC Circuits.h"

using namespace comp;

vector<component *> cmp;

void add_resistor(){
    double res;
    string p_or_s;
    bool a, b(1);

    cout << "You have chosen to add a resistor.\nPlease input the resistance in ohms.\n (If you do not want to add a resistor input 0)\n"; // add in 0 functionality
    cin >> res;
    while(b){
        cout << "Is the resistor connected in series or in parallel?\n";
        cin >> p_or_s;
        if(p_or_s == "Parallel" || p_or_s == "parallel" || p_or_s == "P" || p_or_s == "p"){
            a = 1;
            b = 0;
        }
        if(p_or_s == "Series" || p_or_s == "series" || p_or_s == "S" || p_or_s == "s"){
            a = 0;
            b = 0;
        }
        else{
            cerr << "ERROR: Your selection is invlaid, please input whether the resistor is connected in series or in parallel.\n";
        }
    }

    cmp.push_back(new resistor(res, a));
}

void add_capacitor(){
    double cap;
    string p_or_s;
    bool a, b(1);

    cout << "You have chosen to add a capacitor.\nPlease input the capacitance in ohms.\n (If you do not want to add a capacitor input 0)\n";
    cin >> cap;
    while(b){
        cout << "Is the capacitor connected in series or in parallel?\n";
        cin >> p_or_s;
        if(p_or_s == "Parallel" || p_or_s == "parallel" || p_or_s == "P" || p_or_s == "p"){
            a = 1;
            b = 0;
        }
        if(p_or_s == "Series" || p_or_s == "series" || p_or_s == "S" || p_or_s == "s"){
            a = 0;
            b = 0;
        }
        else{
            cerr << "ERROR: Your selection is invlaid, please input whether the capactior is connected in series or in parallel.\n";
        }
    }
    cmp.push_back(new capacitor(cap, a));
}

void add_inductor(){
    double ind;
    string p_or_s;
    bool a, b(1);

    cout << "You have chosen to add an inductor.\nPlease input the inductance in henries.\n (If you do not want to add an inductor input 0)\n";
    cin >> ind;
    while (b){
        cout << "Is the inductor connected in series or in parallel?\n";
        cin >> p_or_s;
        if(p_or_s == "Parallel" || p_or_s == "parallel" || p_or_s == "P" || p_or_s == "p"){
            a = 1;
            b = 0;
        }
        if(p_or_s == "Series" || p_or_s == "series" || p_or_s == "S" || p_or_s == "s"){
            a = 0;
            b = 0;
        }
        else{
            cerr << "ERROR: Your selection is invlaid, please input whether the resistor is connected in series or in parallel.\n";
        }
    }
    cmp.push_back(new inductor(ind, a));
}

cpp file two:

#include "AC Circuits.h"

int main(){
    return 0;
}

When I move the main to the end of the first cpp file there's no problems, whereas when it's in its own cpp file, LNK1169 and LNK2005 come up, but I'd rather have the main as a separate cpp file.

If it comes to it, I'll just tag it onto the end of the first cpp, but hopefully it won't come to that.

回答1:

Move the definition of the

std::ostream & operator<< (ostream &mm, const comp::complex &c)

in one of the CPP files.

The linker doesn't like this. Personally I'd create a new cpp file for this one too :)



回答2:

When you define a standalone function (with a body) in header file you must use inline (functions defined within class definition are inline by default).

E.g. in header file one must be :

inline ostream& operator<< (ostream &mm, const complex &c){
    if(c.get_im() >= 0){
        mm << "(" << c.get_re() << " + " << c.get_im() << "i)" << endl;
    }
    if(c.get_im() < 0){
        mm << "(" << c.get_re() << " - " << -(c.get_im()) << "i)" << endl;
    }
    return mm;
}

Otherwise you will define this function in each translation unit that includes that header and thus may get multiple definition error.



回答3:

Example to repro LNK1169 & LNK2005 with structs: Place the following in the header file:

    Struct Foo
    {
    std::wstring Bar[3]
    };

    Foo InitFoo[2]
    {
    {L"ConstBar1Val", L"ConstBar1Val2", L"ConstBar1Val3"},
    {L"ConstBar2Val", L"ConstBar2Val2", L"ConstBar3Val3"}
    };

Solution: Move the initialised struct & arrays to the corresponding cpp file.