0

I have this code that I'm trying to debug. It looks okay to me. But I get an error I don't understand.Here's my code

//struct.h
    #ifndef STRUCT_H
    #define STRUCT_H
    #include <iostream>
    using namespace std;

    struct Person {
     Person();
     Person(int a, string n);
     Person(const Person &p);
     Person &operator=(const Person &p);
     ~Person();
     int age;
     string name;
    };

    #endif

//struct.cc
    #include "struct.h"

    Person::Person(): age(0), name("noname") {
     cout << "Creating default Person" << endl;
    }

    Person::Person(int a, string n): age(a), name(n) {
     cout << "Creating: " << name << "," << age << endl;
    }

    Person::Person(const Person &p) {
     name = p.name;
     age = p.age;
    }

    Person& Person::operator=(const Person &p) {
     Person person;
     person.name = p.name;
     return person;
    }

    Person::~Person() {
     cout << "Destroying: " << name << "," << age << endl;
    }

//structMain.cc
    #include "struct.h"
    #include <iostream>
    using namespace std;

    int main() {
     Person one(21, "Zuhaib");
     cout << "I am " << one.name << ". I am " << one.age << " years old" << endl;

     Person two;
     cout << "I am " << two.name << ". I am " << two.age << " years old" << endl;

     two = one;
     cout << "I am " << two.name << ". I am " << two.age << " years old" << endl;
    }

I compile with

g++ -c struct.cc 
g++ -c structMain.cc

g++ -o struct.o structMain.o

I then get the following error

structMain.o: In function `main':
structMain.cc:(.text+0x3b): undefined reference to `Person::Person(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
structMain.cc:(.text+0xb5): undefined reference to `Person::Person()'
structMain.cc:(.text+0x11e): undefined reference to `Person::operator=(Person const&)'
structMain.cc:(.text+0x180): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x18c): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1b8): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1e3): undefined reference to `Person::~Person()'
structMain.cc:(.text+0x1f4): undefined reference to `Person::~Person()'
collect2: ld returned 1 exit status

I think I included all the right files. I double checked the declarations and definitions. I'm just not sure why these errors are coming up. It looks fine to me.

Also, in the main function, what happens at the line

two = one;

I wonder this because, I've overloaded the operator=, but I've also defined the copy constructor which also executes when "=" is encountered. So in the above case, does operator= execute or the copy constructor. Any help would be appreciated. Thanks

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Q_A
  • 433
  • 2
  • 6
  • 14
  • 2
    Please reconsider your use of bad practices [`using namespace std;`](http://stackoverflow.com/q/1452721/1171191) and [`endl`](http://chris-sharpe.blogspot.co.uk/2016/02/why-you-shouldnt-use-stdendl.html). – BoBTFish Mar 07 '16 at 15:35
  • 2
    last line of separated compilation seams strange. Try without `-c` option – Garf365 Mar 07 '16 at 15:36
  • @Garf365. I'm sorry, that was supposed to be a -o. I've changed it – Q_A Mar 07 '16 at 15:40
  • Also, check your assign operator : an assign operator should modify current instance, but not yours. You should write something like that `Person& Person::operator=(const Person &p) { name = p.name; return *this; }` – Garf365 Mar 07 '16 at 15:41
  • 2
    try `g++ -o out struct.o structMain.o` – YSC Mar 07 '16 at 15:41
  • `-o struct.o` will output to `struct.o`, not read it, it that really what you are typing? – Mat Mar 07 '16 at 15:41
  • Try : `g++ -o myapp struct.o structMain.o` after recompiling struct.cc and structMain.cc – Garf365 Mar 07 '16 at 15:41
  • @BoBTFish, Thanks for the advice. However, I've gotten very used to using namespace std; It's hard to program without it. – Q_A Mar 07 '16 at 15:42
  • 4
    @Q_A: get rid of that habit ASAP. – Mat Mar 07 '16 at 15:42
  • 1
    I'm voting to close the question since it's a simple typo resolved in a manner which is unlikely to help others. – YSC Mar 07 '16 at 15:43
  • Just to clarify, I get that error after I run g++ -o struct.o structMain.o – Q_A Mar 07 '16 at 15:44
  • 1
    @Q_A What about if you use what the answer suggest? – NathanOliver Mar 07 '16 at 15:44
  • 1
    @Q_A It might be harder for you to program without it now, but it will be even harder for anyone to read it later. – BoBTFish Mar 07 '16 at 15:46
  • My mistake. So, I've done g++ -o myapp struct.o structMain.o I am getting output. however, the output isn't quite correct. I'll edit my post – Q_A Mar 07 '16 at 15:48
  • 1
    @Q_A: Don't. That would be an entirely different question. – Lightness Races in Orbit Mar 07 '16 at 15:50
  • @Q_A: Your edit renders all existing answers invalid. One question per post, please. – DevSolar Mar 07 '16 at 15:55

2 Answers2

4

When you use:

g++ -o struct.o structMain.o

g++ tries to produce an executable by using the code from structMain.o and put the resulting executable in struct.o. Since structMain.o does not have all the object code to create the executable, you get the linker errors.

You need to use:

g++ -o MyProgram struct.o structMain.o

Here, g++ tries to produce an executable by using the code from struct.o and structMain.o and put the resulting the executable in MyProgram. Assuming you have all the required object code in those two files, that should work.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
2
g++ -o struct.o structMain.o

This tells g++ to take the object code in structMain.o, turn it into an executable, and name that executable struct.o.

As your compiler does exactly what you tell it to, you have just overwritten the object code in struct.o, which happened to hold the definition of your Person class, so yes, the references to that class by structMain.o remain unresolved.

What you want is:

g++ struct.o structMain.o

...or give an explicit output name that is not also the name of one of your input files...

g++ -o someGuessedExecutableName struct.o structMain.o

A common convention is to name a source file after the class it defines, i.e. name it Person.cc and Person.o instead of struct.cc / struct.o... which would have made that error more visible.

DevSolar
  • 67,862
  • 21
  • 134
  • 209