Click here to Skip to main content
15,884,836 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello everyone.I have 3 files in C++. It is my 2nd day with C++ (I have learned C last year in university).
So, my first file is a header file (human.h)
The 2nd file is a .cpp file (human_functions.cpp) and here I implement all the functions/variables I have in human.h
The 3rd file is the main (main.cpp) and here I run my code.

The problem is that in main function when I create an object and compile the code using [ g++ main.cpp -o main ] ,I get this error:
/usr/bin/ld: /tmp/cclgdlYI.o: in function `main':
main.cpp:(.text+0x36): undefined reference to `human___::say_hi_to_human()'
collect2: error: ld returned 1 exit status


What I have tried:

human.h :

class human
{
    public: 
        char *_name_; // his/her name
        int age;    // his/her age
        void check_age();    // check if he/she is an adult
        //void num_of_letters__name();  // number of letters of his/her name
        void check_mood();  //  working and tired => sad , else => happy  
        void check_work();  // check if he/she is working
        void say_hi_to_human();
        void check_tired();

    private:
        bool __tired;
        bool __working;
};





human_functions.cpp :
#include <iostream>
#include "human.h"
#include <cstdlib>

using namespace std;

void human::say_hi_to_human()
{
    _name_ = (char *)malloc(sizeof(char) * 30);
    if( ! _name_ )
    {
        cout << "Not enough space...Sorry" << endl;
        return;
    }
    cin >> _name_;
    cout << "Hello " << _name_ << ".Very nice to meet you" << endl;
}


void human::check_age()
{
    cout << _name_ << " ,how old are you? ";
    cin >> age;
    if(age >= 18)
    {
        cout << "It seems you are an adult since you're " << age << endl;
    }
    else
    {
        cout << "Ooh, you're only " << age << endl;
    }
}

void human::check_work()
{
    char ans;
    cout << "Ok,next question.Do you work this season (Y/N)? ";
    while(true)
    {
        cin >> ans;
        if(ans == 'Y' || ans == 'y')
        {
            __working = true;
            break;     
        }
        else if(ans == 'N' || ans == 'n')
        {
            __working = false;
            break;
        }
    }
}

void human::check_tired()
{
    char ans;
    cout << _name_ << " ,are you tired (Y/N)? ";
    while(true)
    {
        cin >> ans;
        if(ans == 'Y' || ans == 'y')
        {
            __tired = true;
            break;     
        }
        else if(ans == 'N' || ans == 'n')
        {
            __tired = false;
            break;
        }
    }
}

void human::check_mood()
{
    if(__working && __tired)
    {
        cout << _name_ << " ,you have to get some rest..." << endl;
    }
    else
    {
        cout << _name_ << ", I think you're ok and you can continue..." << endl; 
    }
}




main.cpp :
#include "human.h"
#include <iostream>
using namespace std;

int main()
{
    human __human__;
    cout << "Hello. What's your name, please? ";
    __human__.say_hi_to_human();
    return 0;
}




You don't have to look the whole human_functions.cpp.I don't think the problem is there.
I want your help. I appreciate it.
Thanks a lot.
Posted
Updated 8-Oct-21 10:44am

The command
g++ main.cpp -o main
doesn't tell the linker where to find the compiled code for human_functions. Although you've included human.h in your main.cpp, that only includes the class definitions to main.cpp, it doesn't say where the actual code is for the class member functions. Depending on how you want to compile your program, you can either compile human_functions.cpp separately, and then link when you compile main.cpp, or compile both human_functions.cpp and main.cpp at the same time.
Bash
# to compile human_functions  separately
# first create a human_funtions.o (that's what -c does)
$ g++ -Wall -Wextra -g -c human_functions.cpp
#now link human_functions.o with main.cpp
$ g++ -Wall -Wextra -g main.cpp human_functions.o -o main

#to compile both units at once, you can do
$ g++ -Wall -Wextra -g main.cpp human_functions.cpp -o main

# you could also compile each module separately
$ g++ -Wall -Wextra -g -c main.cpp
$ g++ -Wall -Wextra -g -c human_functions.cpp
$ g++ -g main.o human_functions.o -o main 

Note that I've added warning flags to the compiler invocation. I almost always use these two flags, and they will flag most of the useful warnings for you. If you get any warnings, you should take a look at what the compiler thinks might be an issue and almost always, its good practice to fix the code to compile cleanly.
The -g flag is use to add debugging information to the object code. This will aid greatly when the time comes to debug your code.
Lastly, consider using make to compile your code, if you're not using an IDE. A simple Makefile for this project might look like
CXXFLAGS = -Wall -Wextra -g
main: main.o human_functions.o
        $(CXX) -g main.o human_functions.o -o main

You can now say make main, and make will create the .o files and link them together. As a bonus, make knows if a .cpp file is newer than the .o file, so will only compile those modules that need it. This is a Good Thing if you have many modules, and compiling might take many minutes.
Be aware that the third line of the file must start with a tab!
 
Share this answer
 
v2
Check your linker settings: is the human_functions.
 
Share this answer
 
What I did is that I delete #include "human.h" from main.cpp and insert
#include "human_functions.cpp" and now it works.
Is that a good way generally or not?
Thanks.
 
Share this answer
 
Comments
Rick York 8-Oct-21 16:26pm    
NOT! including a source code module in another one defeats one of the primary reasons to have code in separate modules. That would be to improve build times. One should only have to recompile the module(s) that changed. If you only changed human_functions.cpp then you should not have to compile anything else. This is far less an issue now than it used to be but, regardless, that is not recommended practice.
merano99 8-Oct-21 16:30pm    
As you have noticed, it works with a small example, but it is generally unusual and not recommended, as it causes problems with linking in larger projects.

See: What to put in a header file?
https://docs.microsoft.com/en-us/cpp/cpp/header-files-cpp
k5054 8-Oct-21 16:48pm    
Further to what Rick has said, lets imagine you've implemented a stack, with the class header stack.h, and the implementation details in stack_impl.cpp. Now, if you have a program made up of 3 separate files, say main.cpp, automobile_stacks.cpp and aircraft_stacks.cpp, all of which include stack.h. With your solution, each compilation module will include a copy of the source code from stacks.cpp, and compile a copy of the code. This means that each object file (.o) will contain a definition of stack::push(), stack::pop() etc. Now when you try to link the 3 object files together the linker won't know which version of stack::push to link with, and will produce error listing complaining of multiple definitions of stack::push.
I only want to compile main.cpp .What should I include in main.cpp so that I can run it without any problems?You told me a lot of thing on solution 2.
 
Share this answer
 
Comments
k5054 8-Oct-21 17:09pm    
You should probably use the "Have a question or comment" button below a solution to, rather than starting a new solution, if you have further questions about it. When you do that the person proposing the solution should get notification about it and know to respond. Otherwise they might not know that further information is needed.

If you only compile main.cpp, then you'll never get the code from human_function.cpp added to the program. As both Rick York and I have noted in Solution 3, it's not the right thing to do to #include "human_function.cpp" in human.h. If you want to compile in a single step, then use
g++ -Wall -Wextra -g main.cpp human_function.cpp -o main
this compiles and links in a single command line.
Does that answer your question?
Nick_is_asking 8-Oct-21 17:14pm    
Yes,exactly.Thanks you very much all of you for your time.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900