I’m trying to solve a compiling problem regarding outside defined constructor.
Here’s 2 of the classes that have this problem:
//Username.h
#ifndef USERNAME_H
#define USERNAME_H
#include <string>
using namespace std;
class Username{
private:
string Name;
public:
Username(string = "");
string getName() const;
void setName(string);
};
#endif
…
//Username.cpp
#include "Username.h"
Username::Username(string n):Name(n){}
string Username::getName() const{return Name;}
void Username::setName(string n){Name = n;}
…
//User.h
#ifndef USER_H
#define USER_H
#include <string>
#include "Username.h"
using namespace std;
class User{
protected:
Username* UserUsername;
public:
User(string s);
virtual ~User();
Username* getUsername() const;
void setUsername(Username*);
};
#endif
…
//User.cpp
#include "User.h"
User::User(string s):UserUsername(new Username(s)){}
User::~User(){}
Username* User::getUsername() const{return UserUsername;}
void User::setUsername(Username* u){UserUsername=u;}
int main(){return 0;}
If I compile using “g++ User.cpp” I get this error:
/tmp/ccEmWmfl.o: In function `User::User(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
User.cpp:(.text+0x3e): undefined reference to `Username::Username(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
If I use “g++ User.cpp Username.cpp -o main” or if I use inline constructors/destructors I get no error.
These classes are very easy, but I have tons more to compile that require more than one class.
I’m new at compiling in Ubuntu shell with g++, so please, can someone help me to understand?
This compiles User.cpp and attempts to create an executable from it (ie the linker is invoked). Since User.cpp has a symbol not fully defined in User.cpp (the Username constructor here:
the symbol is expected to be defined at the link stage. Linking is done by combining all the generated object file output of all the cpps you generated and piecing together the missing symbols. Here you’re not telling g++ about where to find the full definition of the Username constructor other than the cpp with main, so its failing.
This, however:
Tells the linker where to find full Username definitions (in the object file generated by compiling Username.cpp). So linking can succeed in filling in the missing pieces by using whats defined in Username.cpp to match up identifiers not defined in User.cpp.
You may think — “well I’ve told the compiler about it by including the header file, it should know!”. What you’ve done is declared the symbol. You’ve made a promise that something will eventually be defined, either during compilation of that one cpp or by later linking it with another object file generated by compiling another cpp. g++ needs to know where you intend to pull all your definitions from so it can build a final executable correctly.