Code::Blocks giving me an error on a simple program

Hey all,

I've been using Dev-C++ but am trying to find something a bit simpler. What really confuses me is the difference between source files and header files, what needs the .h and .cpp endings, when to have #include "something.h" or #include "something.cpp". If I have just a function in a source file, what's the deal with the header file? What about a class? I feel I can code fine, at my level, but what to save where and what to "include" is throwing me off.

So I thought I'd try Code::Blocks, as I heard it was a bit simpler. So far, it's not bad. In this program I have a function in it's own source file:

1
2
3
4
5
6
int addition(int a, int b)
    {
        int c;
        c = a + b;
        return c;
    }


In my main.cpp, I have this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

int addition(int a, int b);

using namespace std;

int main()
{
    int one;
    int two;

    cout << "First number: " << endl;
    cin >> one;

    cout << "Second number: " << endl;
    cin >> two;

    cout << "The solution is: " << addition(one, two) << endl;

    return 0;
}


As you can see, I included my function prototype as I should. The error it gives me is in main.cpp, on the final cout line. It says "undefined reference to addition(int, int)". But didn't I reference it with that function prototype? Thanks.
You did, but since the prototype is in an implementation file (.cpp), the linker will be looking within that .cpp (or more correctly, the current translation unit) for its definition.

You should place the prototype in a .h file and have main.cpp and the .cpp that contains the implementation of int addition(int a, int b); include that .h file as well.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>



using namespace std;


int main()
{
    int a;
    int b;

    cout << "First number: " << endl;
    cin >> a;

    cout << "Second number: " << endl;
    cin >> b;

    cout << "The solution is: " << a + b << endl;
    
    system("PAUSE");
    
    return 0;

    
}


Try this one.
Last edited on
Thanks Shacktar. So let me see if I have this right: If I'm writing a class or function, I put it in it's own source file. If it's a function, I make two separate source files, one with the function itself, and the other with its prototype. I then save that prototype as a .h file and have

 
#include "AdditionPrototype.h"; 


at the top of my main.cpp file. Is that right?

And if it's a class I'm writing in it's own source file, I save that file (the class file) as a header file and include it just like I did the AdditionPrototype.h above.

If all that is correct, then I think I finally got the hang of this source/header file stuff :)

And HappyKiller, I know I could do the program like that and avoid the function all together. I'm just pretty much doing this for practice. Thanks though!
Did you create a project or are you just editing source files? Without Code::Blocks knowing about both files at the same time, the linker will be unable to find the addition() function. You know which file the addition() function is in, but the linker isn't psychic. :P

As a result, you must make the IDE aware that the two files are linked in the same project.

On a slightly related note: the learning curve for any IDE can be a bit painful, especially if you get used to a certain way of doing things. :)
Last edited on
Sure, for this example that makes sense. But, what if your function is called in multiple places? What if the function is not so easily inlined? Just replacing the function with equivalent code is not a solution to linking troubles.

EDIT: ninja'd. This was @happykiller
Last edited on
If it's a function, I make two separate source files, one with the function itself, and the other with its prototype. I then save that prototype as a .h file

I find that's the cleanest way to do it. You could place the whole function in a .h file and call it a day, but, that would mean whenever that .h file is included, the whole function is placed in the translation unit (not ideal). If you have a group of closely-related functions, you could place all their prototypes into one .h file and have all their implementations in one .cpp file.

And if it's a class I'm writing in it's own source file, I save that file (the class file) as a header file

If this is what you mean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//myClass.h
class myClass
{
     private:
          int anInt;
          bool aBool;

     public:
          //constructors
          myClass();
          myClass(int a, bool b);
          
          //methods
          void doStuff();
          void doSomeOtherStuff(int& aParam, const char* anotherParam);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//myClass.cpp

#include "myClass.h"

//constructors

myClass::myClass()
{
     anInt = 0;
     aBool = false;
}

myClass::myClass(int a, bool b)
{
     anInt = a;
     aBool = b;
}

//methods
void myClass::doStuff()
{
//...
}

void myClass::doSomeOtherStuff(int& aParam, const char* anotherParam)
{
//...
}


then yes, that's the object-oriented analog to putting prototypes in a .h and the implementations in a .cpp. Some, like myself, prefer to put the "special methods" (i.e. constructors, copy constructor, destructor) in the .h. Again, you could include the class declaration and implementation completely in the .h (you have to do this for template classes, btw), but then you have the same non-ideal situation as above.
Thanks again. I tried out another simple project (which I named Car), but now it's giving me a strange error: "Car - Debug uses an invalid compiler. Probably the toolchain path within the compiler options is not setup correctly?! Skipping... Nothing to be done."

All that between the quotes is what it gives me. Certainly that's nothing wrong with my project, but just incase:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//My header file. I was going to make it a source file, but I didn't know if I could make it a header
//file in the future. I assume this will still work. So, on the left, under Car, I have two sub-folders; Sources and Headers. This is the file under Headers.

#ifndef CARCLASS_H_INCLUDED       //I called my Header file "CarClass.h" and these first three
#define CARCLASS_H_INCLUDED            //lines appeared automatically



#endif // CARCLASS_H_INCLUDED

enum Color {blue, red, yellow, white};

class Car
{
      public:
             Color PaintColor;
             int NumOfDoors;
             int GasLevel;
             
             void start_engine()
             {
                  GasLevel -= 1;
             }
             
             void take_for_spin(int NumOfMiles)
             {
                  cout << "You took it for a spin of " << NumOfMiles << " miles!" << endl;
                  
                  GasLevel -= NumOfMiles;
             }
             
             void check_gas_level()
             {
                  cout << "Your gas level is currently: " << GasLevel << endl;
             }
};



My main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "CarClass.h"

using namespace std;

int main()
{
    Car MyCar;
    MyCar.PaintColor = red;
    MyCar.NumOfDoors = 4;
    MyCar.GasLevel = 25;
    
    MyCar.check_gas_level();
    MyCar.take_for_spin(22);
    MyCar.check_gas_level();
    
    return 0;
}


I don't know why it would tell me there's noting to be done (unless it's just lazy!).
Last edited on
"Car - Debug uses an invalid compiler. Probably the toolchain path within the compiler options is not setup correctly?! Skipping... Nothing to be done."

I haven't used Code::Blocks before but this sounds like an IDE setup issue. Probably the compiler (e.g. MinGW) is not attached to your project. Sorry I can't help you any more than that.

1
2
3
4
5
6
#ifndef CARCLASS_H_INCLUDED       //I called my Header file "CarClass.h" and these first three
#define CARCLASS_H_INCLUDED            //lines appeared automatically



#endif // CARCLASS_H_INCLUDED 


If you want to know what this is, it's called an include guard. Essentially, it prevents a .h file from being #include d multiple times in the same translation unit (otherwise it would generate a linker error). However, with the way you have it, it just prevents a bunch of white space from being included multiple times. What you should do is put the #endif // CARCLASS_H_INCLUDED at the bottom of the .h file. Another way to prevent multiple #include s is to simply add #pragma once at the top of your .h (though this isn't fully supported and you may run into troubles with this, especially on older compilers).

Another thing I noticed that will give you problems is in "CarClass.h", you're not placing std:: in front of cout and endl. You need to do this because your .h is not using namespace std;, only main is. Either put using namespace std; in "CarClass.h" or put it above the #include "CarClass.h" statement in main.cpp. Although I don't think putting it within the .h file is good style because that would make any file that includes CarClass.h also use the standard namespace (maybe not what that file wanted!). It may be better just to use std:: within the .h, but really it's up to you.
@I don't know why it would tell me there's noting to be done (unless it's just lazy!).

Yeah, that line alone does tell me MinGW isn't installed. Do you even have a folder in the default path. C:\MinGW
Don't know why anybody would use an IDE without installing a compiler, unless you're using someone else's computer.

Also the above persons post will solve your issue, you've basically written code which is never included therefore the definition is never compiled.
Last edited on
I see! Thanks. You're right, I had installed the non-MinGW version. As a newbie, I didn't know MinGW was the actual compiler. I'll install that one!
Topic archived. No new replies allowed.