Utilities class?

I had made a couple of custom data types up to this point that I used instead of floats. For example, I had a Dimensions struct that worked like a Vector2 but had a “width” and “height” instead of “x” and “y”. I also had a VectorZero Vector2 setup so I didn’t have to keep initializing a new one everytime I needed to reference 0,0.

But when I made the Character class, all this stuff became unavailable. So I copied and pasted them to the character.cpp and now it all works, but I have redundant code. Now I guess I could put those things in their own “utilities” file and just “#include” that, but I’m a bit confused because I thought by putting these structs and variables outside my “main” function in main.cpp, they would be accessible anywhere in my program, including other classes.

Is this because the “#include” lines are at the top before those structs and variables? I think that’s the case. But if so, can I just move those lines down below the “utiltiy” structs and variables that I wanted to be global? Or do they have to be at the top?

Or should I just create the utilities files and then “#include” them in every single file everywhere?

(This may be moot in this specific example because I may not need the custom data types to organize my info anymore now that I have variables connected to a specific class. Instead of “width” or “knight_width” or “knightDims.width”, for example, I now have “knight.width”, a “width” float specific to the Character class instance “knight”)

I’m not a TA but I think I can help you out.

At a fundamental level when a cpp file is compiled, the compiler wholesale copies and pastes any header file referenced and just dumps it where it was referenced.

If the code you want to use doesn’t exist inside any of the header files you’ve included, nor is it included in your source file, then it effectively doesn’t exist when compiling.

So the solution to your problem is in fact to make a utilities class and drop the include wherever you need it.

If you’re interested, a youtuber named “The Cherno” explains this quite well here

Ah, our instructor “includes” the necessary info under the lecture titled “Class Inheritance”, explaining how to write a class that only ever gets included once no matter how many times it appears in #include lines.

To note that’s only per translation unit (compilation of a source file after the preprocessor has ran, essentially). It will not protect you from One Definition Rule(ODR) violations.

e.g.
Foo.h:

#pragma once
int square(int n)
{
    return n * n;
}

A.h:

#pragma once
#include "Foo.h"

B.h

#pragma once
#include "Foo.h"

main.cpp

#include "A.h"
#include "B.h"

int main()
{
    int value = square(3);
}

This will only include Foo.h once and you’d end up compiling the file

int square(int n)
{
    return n * n;
}
int main()
{
    int value = square(3);
}

All well and good no ODR issues. Now lets add Bar.cpp:

#include "Foo.h"

int bar()
{
    return square(5);
}

Which results with the file with square defined above. If you now try to compile and link that

g++ main.cpp bar.cpp

You will now get an ODR violation as you have 2 definitions of square, one in the compiled object file for main and another in the object file for bar and the linker has no idea which one to use so will result in a linker error.

So you need to be careful with defining variables and functions in headers as you can easily get ODR problems. One solution is to use the inline keyword which in modern usage means “linker, all of the definitions are all the same, trust me” and if they aren’t then you have undefined behaviour.

Declaring things multiple times isn’t an issue so if you just put the declaration in the header and define it in one .cpp you shouldn’t get ODR problems.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms