![]() |
|
Splitting up source into different .cpp and .h files |
Felix-The-Ghost
Member #9,729
April 2008
![]() |
Hi all, This is a topic I've attempted to learn time and time again. I have been coding with all my code in one long file instead of multiple focused files (like I want) But splitting up my code is hard for me to grasp how to do, for some reason. I don't think I'm completely stupid, but I think I should have gotten this like a long time ago... I'm trying to learn it from this article The way I've written my functions requires variables known across source files (global variables, I guess, which I'm told are bad) I'm having trouble implementing this part of the article: Quote: For convenience, some people like to put all the 'extern' declarations into a globals.h file, and all the actual definitions into a globals.cpp file. When I use externs it says the variables were never defined, when I don't, it says I've declared them more than once. I use global variables cause I like having functions that already know about other variables so I can do stuff like void new_game() { TheHead.x = Buffer->w/2; TheHead.y = Buffer->h/2; TheBody.clear(); AllFood.clear(); score = 0; mult = 1; combo = 0; game_loop = 0; } instead of void new_game(head* h, vector <int>* b, vector <int>* f, int* s, int* m, int* c, int* g_l) { h.x = Buffer->w/2; h.y = Buffer->h/2; b.clear(); f.clear(); s = 0; m = 1; c = 0; g_l = 0; } I realize the code above probably does not even work (I need to re-learn pointers syntax every so often) But is that how I should write my code (passing pointers to variables into them so they don't have to know about them already)? Cause I just kinda like how new_game(); looks as opposed to new_game(&TheHead, &TheBody, &AllFood, &score, &mult, &combo, &g_l); Although I do realize the latter is probably more "reusable." I'm honestly having trouble learning this so please don't make fun of me or tell me to RTFM or JFGI or kill myself/delete system32. I hope this post makes sense 'cause I have a headache now How do you guys split up your functions, initializations, declarations, etc? Currently I'm stuck at 1 header file with extern declarations
|
amber
Member #6,783
January 2006
![]() |
Felix-The-Ghost said: I like having functions that already know about other variables
From your use of STL vectors, it seems like you're using C++, but you're not using one of the most useful parts of C++. You should probably read up on object-oriented programming because it seems like you'd benefit a lot from it. Basically, a function that is a member of a class will know about variables that have been declared as part of that class. For example, you could make a class like: class GameData { int state; int money; int player_alive; // and so on public: void newgame(); }; You can write your newgame function like: void GameData::newgame() { state = 0; money = 100; player_alive = 1; // or whatever }
See how it already knows about all of the variables you've declared inside of the class. Somewhere (you can even do it globally if you want) create an object, i.e., an instance of the class, like this: Then you can just do game.newgame() like you want to. This is just a brief (and probably not too useful) introduction, but it should at least point out the concepts you can read more about. Once you've got these ideas down, it becomes easier to break your program across files, because you can do things like put each class in its own file, or the like. |
gnolam
Member #2,030
March 2002
![]() |
1#include "bar.h"
2
3void some_function(void)
4{
5 some_global++;
6}
1#ifndef BAR_H
2#define BAR_H
3
4extern int some_global;
5
6#endif
1int some_global = 666;
(I'll leave it to someone else to explain why globals are considered harmful, why the void new_game() example you gave is hard to follow and unmaintainable, [EDIT] -- |
Felix-The-Ghost
Member #9,729
April 2008
![]() |
I've used classes before in other projects, and I thought about putting like everything into one class or struct but I wondered if that would be another "bad practice." I read somewhere about "encapsulating globals into a class" or something which is what I think you're talking about. I guess the prefix "class_name::" isn't nearly as bad as passing variables directly into a function. Thanks, I think I know enough to try that idea soon. Although I need to look in my old projects how I did class definitions. Am I gonna need an external declaration, too? At least it'd be one with everything in it. |
David Sopala
Member #5,056
September 2004
|
It takes some thinking sometimes... Think of something like an [item] in a game now we have different flavors of [item]s like [weapon]s, [armor]s, [metal]s, and whathaveyou. So something like that you might have a class called item and a few more classes that are all items so they would inherit from item. So you can have something like player->use_item(item myitem); global variables can be accessed by everyone everywhere - this leads to problems when you get deeper into coding. Especially when you have multiple people working on a project guy 1 changes something that breaks guy 2's code all kinds of weirdness. Don't think of classes as containers; think of them as though you were building an actual game in front of you. You might want a wall and who knows bricks in the wall even - depending on what can happen to said wall... I will say this currently in the server I am writing I have around 24 files, but my main source file is only 240 lines long. Classes help alot and once you understand them you will ask how you ever did stuff without them. <img src="http://imgur.com/bfHvGkj.jpg" /> |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Felix-The-Ghost said: I realize the code above probably does not even work (I need to re-learn pointers syntax every so often) But is that how I should write my code (passing pointers to variables into them so they don't have to know about them already)? You didn't access the pointers properly. You need to use -> to access members and methods, and you need to use * to access the data pointed to by a pointer. Felix-The-Ghost said: I've used classes before in other projects, and I thought about putting like everything into one class or struct but I wondered if that would be another "bad practice." I read somewhere about "encapsulating globals into a class" or something which is what I think you're talking about. Smashing everything into a single class is not what you want to do. That's the same thing as putting everything into a single main.cpp file. You need to logically organize related data using structs or classes. Using your original example, this would be an improvement : Using structs : 1typedef struct Game {
2 head h;
3 vector<int> b;
4 vector<int> f;
5 int s;
6 int m;
7 int c;
8 int g_l;
9};
10
11void new_game(Game* g);
12
13int main(int argc , char** argv) {
14 Game g;
15 new_game(&g);
16 return 0;
17}
18
19void new_game(Game* g)
20{
21 g->h.x = Buffer->w/2;
22 g->h.y = Buffer->h/2;
23
24 g->b.clear();
25 g->f.clear();
26
27 g->s = 0;
28 g->m = 1;
29 g->c = 0;
30
31 g->g_l = 0;
32}
Now to organize your source and header files, you would put the Game struct declaration in a header file by itself (Game.h) along with the prototype for new_game. Then you would put the definition for new_game into Game.c. After that you would include Game.h in main.c. Now everything is logically organized. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
bamccaig
Member #7,536
July 2006
![]() |
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Felix-The-Ghost
Member #9,729
April 2008
![]() |
bamccaig
Member #7,536
July 2006
![]() |
Felix-The-Ghost said:
It's just weird thinking of the game as an object
A "game" is a noun, and therefore an object. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Felix-The-Ghost
Member #9,729
April 2008
![]() |
Well when I think of "object" I usually think of material, tangible things (Or things that would be tangible outside the software). I understand a class of tank or bullet but it's new to me to have the program itself be an "object". But I do understand why it works now. I haven't had time to try to implement it yet. I guess I could use a struct for non-"tangible" things if I were to be really anal about it (aren't structs and classes functionally the same in C++?) |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
In C++ structs are public by default, and classes are private by default. That's the only real difference. But it's common for structs to be used as simple data sets and classes to be used as fully functional objects. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
David Couzelis
Member #10,079
August 2008
![]() |
"I do realize the latter is probably more reusable." My advice is to simply program it the way that makes it easier for you to understand. Don't waste time making code more reusable, because you're never going to reuse it. If you're working on a project some time in the future and you DO want to reuse it, THAT'S when you make it reusable. |
|