• C++ Class/Other data declaration
    23 replies, posted
Simple question, probably. Why, in C++ are classes declared, and then outside of the class the functions are implemented as in Class::Function instead of doing all of it inside the class, and having it look a lot cleaner? Basicly, why [code] class Foo { private: int Bar; int FBar; public: void SetBar(int B); void SetFBar(int FB); int Multiply(); } void Foo::SetBar(int B) { Bar=B; } void Foo::SetFBar(int FB) { FBar = FB; } int Foo::Multiply() { return (Bar*FBar); } [/code] Instead of this [code] class Foo { private: int Bar; int FBar; public: void SetBar(int B) { Bar=B; }; void SetFBar(int FB) { FBar = FB; }; int Multiply() { return (Foo*FBar); }; } [/code]? To me, the second looks much cleaner.
One reason is to seperate interface from implementation. Another reason is so that if that file is found multiple times in the same project or whatever, it will treat them as multiple declarations of the same function, and you'll get a compiler error (unless it's a template class, in which case you have to have the function definitions inline). So you have the class definition in a header file and the function definitions in a .cpp file, so the class definition can appear multiple times but the function defs appear only once.
As yakahughes said, to seperate the interface from the implementation of the member functions. In your first example the class will behave that way and will ALWAYS behave like that and has no reason to be changed, it is good programming practice and is called prototyping. Only the corresponding source file for the header file will need to be changed if changes need to be made. In your second example if you messed up you will need to waste time sifting through the implementation of the interface of your functions and possibly messing that up too. To analogise, if you want to fix your TV, you want the buttons on the front of the TV to always look the same and do the same thing as before, you only want to muck about with what the buttons DO, the actual buttons are of no importance. This isn't the only reason, this is only in terms of maintenance and readability.
Many reasons. 1. When repeatedly including lots of headers that are full of code, your compile time will shoot up. 2. If you want to create a library like DirectX or whatnot, all your code is going to be in plain view and at the mercy of the compiler. 3. C++ is a single pass compiler, unlike C# or Java or any other modern language pretty much. This means definitions must appear above usages. If you write code in a header, there's a high chance of ending up with cyclic dependencies. ie, Lets say class Foo has a member of type Bar that we access in the code. And class Bar has a member of type Foo that was access in the code. To use these 2 members, we need to include the other classes header. This will create a cyclic dependency whereby the headers will be attempted to be repeatedly included and you'll never get the actual definition you need. [code] ---------------- Foo.h: ---------------- #include "Bar.h" class Foo { void DoThing( ) { mBar->DoSomething( ) } void DoSomething( ) { } Bar* mBar; } ---------------- Bar.h: ---------------- #include "Foo.h" class Bar { void DoThing( ) { mFoo->DoSomething( ) } void DoSomething( ) { } Foo* mFoo; } [/code] Each file tries to include the other one, and we'll never get the definition that is required to use the other class. So instead we DECLARE in a header file, but DEFINE in an implementation file. [code] ---------------- Foo.h: ---------------- class Bar; class Foo { void DoThing( ); void DoSomething( ); Bar* mBar; } ---------------- Foo.cpp: ---------------- #include "Foo.h" #include "Bar.h" void Foo::DoThing( ) { mBar->DoSomething( ); } void Foo::DoSomething( ) { } ---------------- Bar.h: ---------------- Class Foo; class Bar { void DoThing( ); void DoSomething( ); Foo* mFoo; } ---------------- Bar.cpp: ---------------- #include "Bar.h" #include "Foo.h" void Bar::DoThing( ) { mFoo->DoSomething( ); } void Bar::DoSomething( ) { } [/code] Bet I made some silly mistake writing that :P
[QUOTE=knighty;28078056]usefulluess[/QUOTE] Ah, that makes sense. Thank you. One more question as to the way you wrote that. In the first example, at the end you have Bar* mBar etc, and from inside the class you use this pointer(?). I'm really new to C++, so could you explain what this does?
Bar* mBar and Foo* mFoo are just member variables of the Foo and Bar classes, respectively. He's calling the DoSomething method on both of those objects. Also that's a thing you want to avoid if you can't tolerate mFoo and mBar being NULL, because in the constructor of each you'll want to initialize mFoo and mBar to variables, but in doing so you'll create an infinite loop and crash with a stack overflow.
-> dereferences the pointer and allows you to access data or it can be used to call member functions in that type. The pointer points to an area of memory, and by using -> we can access the data at that memory location. It's basically shorthand for (*pointer).data. Yaka, that would only apply if they were objects. Here they are pointers, and can thus always be null. It's actually physically impossible for them to both be objects, because you cannot use forward declarations, ie class Foo; to declare a member OBJECT of that type. You can do it with pointers because they are always the same size, 32bits or 64bits, depending on whether your app is 32 or 64bit.
[QUOTE=knighty;28078360]-> dereferences the pointer and allows you to access data or it can be used to call member functions in that type. The pointer points to an area of memory, and by using -> we can access the data at that memory location. It's basically shorthand for (*pointer).data. Yaka, that would only apply if they were objects. Here they are pointers, and can thus always be null.[/QUOTE] Oh, I see. They are defined inside the class brackets, thats how they can be accessed in that context. I thought they were outside the brackets. One more question, if you might. If I have a main.cpp, and then a Particle.h and Particle.cpp and they're in the same directory, in main.cpp I could just <include Particle.cpp> correct? (considering that Particle.cpp has <include Particle.h> in it)
[QUOTE=bobthe2lol;28078416]I thought they were outside the brackets.[/QUOTE] And that's the importance of proper indentation.
There only would have been a couple of indents, it's not that deeply nested
[QUOTE=yakahughes;28078437]And that's the importance of proper indentation.[/QUOTE] I would have indented it, had I written it in something other than the post reply textbox :P Sorry if it was unclear. [editline]16th February 2011[/editline] [QUOTE=bobthe2lol;28078416]Oh, I see. They are defined inside the class brackets, thats how they can be accessed in that context. I thought they were outside the brackets. One more question, if you might. If I have a main.cpp, and then a Particle.h and Particle.cpp and they're in the same directory, in main.cpp I could just <include Particle.cpp> correct? (considering that Particle.cpp has <include Particle.h> in it)[/QUOTE] No, see that's the point of definition vs declaration. You only include Particle.h. That contains everything the compiler needs to know to work with the implementation file.
[QUOTE=knighty;28078462]I would have indented it, had I written it in something other than the post reply textbox :P Sorry if it was unclear. [editline]16th February 2011[/editline] No, see that's the point of definition vs declaration. You only include Particle.h. That contains everything the compiler needs to know to work with the implementation file.[/QUOTE] Ehm... then how does the compiler know that Particle.cpp exists if I only include the header file, which doesn't include Particle.cpp? And I thought I understood it haha. This is how I see it: Particle.cpp implements class(es) from Particle.h, and then main.cpp uses the implemented classes from Particle.cpp. I'm wrong.
[QUOTE=bobthe2lol;28078521]Ehm... then how does the compiler know that Particle.cpp exists if I only include the header file, which doesn't include Particle.cpp? And I thought I understood it haha.[/QUOTE] In the linking stage (after all the files have been compiled and the compiler knows what functions are used) it looks for the appropriate function definitions for the functions that were used. If it doesn't find one, it stops and emits a linker error. If it does find them, it links the function calls to the actual code. This is how you can distribute just the header files for functions and a static library, and just link to the library and the compiler will know what to do.
in the Particle.cpp you include the Particle.h header file too and refer to the functions in terms of the class name as such: [code]void Foo::SetBar(int B)[/code] This reference links the definition with the interface and you're good to go
[QUOTE=Kondor58;28078594]in the Particle.cpp you include the Particle.h header file too and refer to the functions in terms of the class name as such: [code]void Foo::SetBar(int B)[/code] This reference links the definition with the interface and you're good to go[/QUOTE] Yeah, and then if I want to use the class Foo in main.cpp, I include Particle.cpp, which has the working definitions in it?
The compiler doesn't touch the header files. The compiler only compiles the cpp files. So first it goes and compiles your Particle.cpp file. This gets compiled into a .obj file (if you're working in visual studio). Next it'll compiler your Main.cpp file into a .obj file. Then we get to a process called linking. Here we just link up functions that are called from each file with the actual function that appears in the .obj file. When compiling, the compiler doesn't need to know how a function in your particle class works, all it needs to know is what to expect it to return, and what inputs it takes in. If you're writing this outside of an ide, you'll need to create a Make file to tell it to compile Main.cpp and Particle.cpp.
[QUOTE=bobthe2lol;28078613]Yeah, and then if I want to use the class Foo in main.cpp, I include Particle.cpp, which has the working definitions in it?[/QUOTE] No, you only include the header file, the definitions are linked to the interface so you only need to include the interface (header file)
[QUOTE=knighty;28078622]The compiler doesn't touch the header files. The compiler only compiles the cpp files. So first it goes and compiles your Particle.cpp file. This gets compiled into a .obj file (if you're working in visual studio). Next it'll compiler your Main.cpp file into a .obj file. Then we get to a process called linking. Here we just link up functions that are called from each file with the actual function that appears in the .obj file. When compiling, the compiler doesn't need to know how a function in your particle class works, all it needs to know is what to expect it to return, and what inputs it takes in. If you're writing this outside of an ide, you'll need to create a Make file to tell it to compile Main.cpp and Particle.cpp.[/QUOTE] Oh. I'm using Code::Blocks, and that makes a bit more sense to me. The compiler doesn't care what happens to the inputs to get the outputs, it just cares what they are, then at runtime the functions is actually called and ran, right? [editline]15th February 2011[/editline] [QUOTE=Kondor58;28078646]No, you only include the header file, the definitions are linked to the interface so you only need to include the interface (header file)[/QUOTE] I (think) I understand it now. I was thinking of it too much like java I guess.
That's pretty much it yeah. Sort of anyway, the compiler actually does care about what happens to the inputs but that's an aside issue (to do with const if you want to look it up). A function is just code at a specific point in memory. The linker just takes all your calls to that function and maps it to where the function actually ended up in your .exe/.lib/.dll/whatever.
Thanks so much! All of you!
You're very welcome.
Bah, never mind. This is not what this thread is about. I'll post it in the help thread. If you still want to help though, [quote=bobthe2lol] Oh, crap. Now I'm having a compiler error that makes no sense. [code] /Particles/src/Particle.cpp|8|error: ISO C++ forbids declaration of &#8216;Change&#8217; with no type| /Particles/src/Particle.cpp|8|error: prototype for &#8216;int Particle::Change()&#8217; does not match any in class &#8216;Particle&#8217;| include/Particle.h|16|error: candidate is: void Particle::Change()| [/code] Particle.h is [code] class Particle { public: Particle(int x, int y); //blah blah void Change(); //line 16 }; [/code] and Particle.cpp [code] #include "Particle.h" Particle::Particle(int x, int y) { this->Setxy(x,y); } Particle::Change() { this->Setxy((x*xSpeed),(y*ySpeed)); } [/code] What could possibly go wrong? [/quote]
[QUOTE=bobthe2lol;28079155]Bah, never mind. This is not what this thread is about. I'll post it in the help thread. If you still want to help though,[/QUOTE] [code]#include "Particle.h" Particle::Particle(int x, int y) { this->Setxy(x,y); } void Particle::Change() { this->Setxy((x*xSpeed),(y*ySpeed)); }[/code] the only functions that dont have a type are the constructor and the destructor
[QUOTE=Richy19;28079361][code]#include "Particle.h" Particle::Particle(int x, int y) { this->Setxy(x,y); } void Particle::Change() { this->Setxy((x*xSpeed),(y*ySpeed)); }[/code] the only functions that dont have a type are the constructor and the destructor[/QUOTE] Oh!!! Forgot the void! Haha, thanks!
Sorry, you need to Log In to post a reply to this thread.