-2

Getting c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: main.o:main.cpp:(.text+0x2b): undefined reference to (insert my methods in ComplexNumber.cpp) when compiling using a makefile after the G++ main.o ComplexNumber.o -o output is being ran.

I have tried checking online for places I may have missed a and used my other header files I have done in the past for reference to check for errors there, but I have had no luck. I am using cygdrive on windows to compile, but have also tried just using mingw on regular command prompt as well.

Header File: '''''''''''''

#include <stdio.h>


#ifndef COMPLEXNUMBER_H_
#define COMPLEXNUMBER_H_



template<typename T>

class ComplexNumber
{

    public:
        // a is a real number, b is a complex number
        T a;
        T b;
        ComplexNumber();
        ComplexNumber(T, T);
        void toString();
    ComplexNumber operator +(ComplexNumber<T>& c);
    ComplexNumber operator *(ComplexNumber<T>& c);
    bool operator ==(ComplexNumber<T>& c);
};



#endif /* COMPLEXNUMBER_H_ */

''''''''''''''

ComplexNumber.cpp ''''''''''''''

#include <iostream>
#include <stdlib.h>
#include <ctime>
#include "ComplexNumber.h"


using namespace std;


template <typename T>

    ComplexNumber<T>::ComplexNumber()
    {}
template <typename T>
ComplexNumber<T>::ComplexNumber(T a, T b)
{
    this->a = a;
    this->b = b;
}
template <typename T>
ComplexNumber<T> ComplexNumber<T>:: operator +(ComplexNumber& c)
{
    ComplexNumber <T> temp;

    // adds the complex numbers, (a+bi) + (c+di) = (a+b) + i(c+d)
    temp.a = this->a + c.a;
    temp.b = this->b + c.b;
    return temp;
}
template <typename T>
ComplexNumber<T> ComplexNumber<T>:: operator *(ComplexNumber& c)
{
    ComplexNumber<T> temp;

    // multiplies complex numbers, (a+bi) + (c+di) = (a*c-b*d) + i(a*d + b*c)
    temp.a = (this->a * c.a) - (temp.b * c.b);
    temp.b = (temp.a * c.b) + (temp.b * c.a);
    return temp;
}
template <typename T>
bool ComplexNumber<T>:: operator ==(ComplexNumber<T>& c)
{
    ComplexNumber<T> temp;

    // compares complex numbers to see if they're equal, (a+bi) == (c+di) -> if (a==c) & (b==d)
    if (temp.a == c.a && temp.b == c.b)
    {
        cout<< "The complex numbers are equal."<<endl;
        return true;
    }
    return false;
}
template <typename T>
void ComplexNumber<T>::toString()
{

    cout<< "("<< this->a<< " + "<< this->b<< "i)"<<endl;
}

MakeFile: ''''''''''''''

all: ComplexNumber
ComplexNumber: main.o ComplexNumber.o
    g++ main.o ComplexNumber.o -o output
main.o: main.cpp
    g++ -c main.cpp
ComplexNumber.o: ComplexNumber.cpp
    g++ -c ComplexNumber.cpp
clean:
    rm *.o output

''''''''''''''

thej1996
  • 1
  • 1
  • 1
    Create your definitions to the header file. – Michael Chourdakis Apr 14 '19 at 06:25
  • 1
    @MichaelChourdakis is right. Looks like you ran into [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – user4581301 Apr 14 '19 at 06:46
  • @MichaelChourdakis What do you mean by my definitions exactly? like my definition of temp? Sorry am very new to C++ pretty much have only done Java in school. Thank you for helping!. – thej1996 Apr 14 '19 at 08:57

1 Answers1

-2

@thej1996, You can solve it in two ways: 1) Include both Header & cpp file (ComplexNumber.h/ComplexNumber.cpp) in your client application(client.cpp file which invokes ComplexNumber usage). 2) Alternatively provide a temporary function in your template cpp file(ComplexNumber.cpp) to avoid linker error:

void TempFn ()
{
    ComplexNumber<int> ComplexObj;
}

No need to call this function anywhere. Just to satisfy the linker.

dennis
  • 680
  • 1
  • 5
  • 11
  • Putting the void TempFn in the ComplexNumber.cpp has unfortunately not fixed my undefined reference to errors. Including ComplexNumber.cpp in my main.cpp did work, but doesn't that somewhat defeat the purpose of the header file in a way? I'm pretty new to C++ so I definitely find the header files in general a bit confusing but am slowly getting there. – thej1996 Apr 14 '19 at 09:03
  • Templates are normally designed to be defined in header files itself, but what I understood from your requirement was that you really needed to decouple the implementation(source .cpp) from interface(header .h). So, I suggested this way around. – dennis Apr 14 '19 at 09:37
  • @dennis Both of your proposals will lead to even more problems. 1. Will screw up any decent build system (because it will try to compile `ComplexNumber.cpp` a second time standalone) General rule: Never `#include` .cpp files. 2. Will become a maintenance hell, this needs to be done for each and every type used with the template. – πάντα ῥεῖ Apr 14 '19 at 09:38
  • I agree, but the author requested a "way around", which I have suggested. As I told before, templates are designed to be implemented in header files, but if he still needs it the other way, so there exists a clumsy way which I have pointed out in my answer. Ofcourse I myself will never use these way arounds and would just use templated header files containing definition. – dennis Apr 14 '19 at 09:42