   Getting away from "C with classes" (C++)
  I started coding in C without classes by following some tutorials and since reading up on C++ rewrote everything with classes now (a few months ago).  Lots cleaner especially with outlining in VC express, way easier to implement ideas as 'objects' and no global variables.  [In a couple cases I've had variable sized multi dimensional arrays that I decided it wasn't worth the obfuscation to my un-trained self to make them variable and just kept them hard coded.  I think the pitfall was I couldn't make the sizes of these arrays dependent on another object and in a default constructor.]BUT I feel like I'm doing it wrong because I kept everything public in my classes.I have 2 classes with similar members (pre-computed size & translation type constants for functions to work with pre-computed sized arrays) that interact with eachother (ie passed one to the other by reference in ones member functions) and have had no problems with similarly named variables.If I make the member variables private, they are no longer available to that other class the object was passed to, so the only way I could see of getting the values to the other class is passing them individually in the argument list which could get to be really big.So in this case it seems like it would be so much work to go through and a) see which variables are used in each function and only make those public which are ever used by another class and make the rest private orb) to rewrite all the functions that take variables from other classes to take the values as separate arguments instead of the object as 1 argument.Go on?  Make the changes?  Do something else?  Thanks to anyone who can make a suggestion, these forums have been really informative and are great to read.Here's also the big header file, my other one (system) is small, 1 class, 2 functions.#ifndef GAME_H#define GAME_H#include <cmath>#include <iostream>#include <SDL/SDL.h>#include <SDL/SDL_opengl.h>#include "system.h"class Region;class Game;class Vectorf{public:float vector[3];};class ShiftFault{public:int ax;int az;int abx;int abz;void set_me(int ax, int az, int bx, int bz);int part_test(int px, int pz, int Fac);};class World{public:int nsize;int size2n;int size2nplus1;int halfsize;int lastSeed;int secsize;int numfaults;int faultfac;ShiftFault* faults;World(int sizeIn, int secsizeIn, int numfaultsIn, int faultfacIn);void setFaults();int getFaultSum(int globX, int globZ);int getglobX(int seedCoord);int getglobZ(int seedCoord);int seedCoord(int globX, int globZ);float getElev(int globX, int globZ, int yShift, float hFac, float persist);};class Sector{public:int id;int globX;int globZ;float height;void setTo(int xcoord, int zcoord, World& theWorld);void setHeight(World& theWorld);};class Player{public:unsigned int sector_x, sector_z;float myX, myY, myZ;float myLX, myLY, myLZ;int mydirX, mydirY, mydirZ;float mySpd;float myTheta, myPhi;Player();void interpY(Region& theRegion, World& theWorld);int inSector(World& theWorld);void moveMe(Region& theRegion, World& theWorld);};class ClipMap{public:int level;int tvect_x;int tvect_z;int tvect_x_secsize;int tvect_z_secsize;int unit;int unit_secsize;int half_unit_secsize;int width;float zBuf_inner;float zBuf_outer;int player_mod_x;int player_mod_z;int clip_l;int clip_u;int shiftmod_x;int shiftmod_z;int shiftmod_not_x;int shiftmod_not_z;int shiftmod_notx_notz;int shiftmod_x_and_z;int shiftmod_notx_and_z;int shiftmod_x_and_notz;Sector sectors[257][257];Vectorf normals[257][257];inline void setPlayerMods(Player& thePlayer);inline void setTvects(Player& thePlayer, Region& theRegion, World& theWorld);inline void setClips(Region& theRegion);inline void setShifts(Region& theRegion);void setMeta(int F, Region& theRegion, World& theWorld);void setVars(Player& thePlayer, Region& theRegion, World& theWorld);void setSectors(Player& thePlayer, Region& theRegion, World& theWorld);void setNormal(int ii, int jj, Vectorf& theVectorf, Region& theRegion);void setAllNormals(Region& theRegion);void shiftSectors(int x, int z, Player& thePlayer, Region& theRegion, World& theWorld);void drawMap(Game& theGame, Region& theRegion, World& theWorld);};class Region{public:int n;int depth;unsigned int size2n;unsigned int halfsize;unsigned int size2nplus1;unsigned int size2nmin1;unsigned int size2nmin2;unsigned int clipmapsize;ClipMap* maps;Region(int n_in, int depth_in, Player& thePlayer, World& theWorld);void setAllMaps(Player& thePlayer, World& theWorld);void setMap(int F, Player& thePlayer, World& theWorld);void checkMaps(Player& thePlayer, World& theWorld);void drawDistant(Game& theGame, World& theWorld);};class Game{public:GLint T0, Frames;SDL_Event myEvent;System* systemPointer;bool gameRunning;bool isActive;Game();void assignSystem(System& theSystem);void pollSDLevents(Player& Player);void updateGame(Player& Player, Region& theRegion, World& theWorld);void mouseLook(Player& Player);void render(Player& Player, Region& theRegion, World& theWorld);void mainLoop();};#endif[Edited by - PrestoChung on May 21, 2010 11:19:56 AM]
  The following is strictly of my own experience and preferences:the public or private thing is a difficult one to determine, it all depends on the intended use of the class, how important it is to not have a variables changed/obtained by outside influences and personal preferance.There are several reasons your public interface may have member variables. for example, take a math vector class:class Vector2{public:float X, Y;};Here we can see that the Vector2 class' public interface consists of 2 variables that allow a client programmer to easily access and modify the values that they hold. Which is how it should be, since we will need to be setting and getting the X and Y position of a game entity almost every frame (excluding some 'static' objects like environment props, we only sometimes need to 'get' those).However, consider what it would be like to have 'Get' and 'Set' methods for each of those variables.class Vector2{float X, Y;public:float GetX( ) const;float GetY( ) const;void SetX(float);void SetY(float);};Besides the second snippet of code looking damn ugly, this is poor design and completely redundent. The only thing you would be achieving here is more work for both you and your client (which is more often than not yourself).Now consider this second example to do with the windows API:class BaseWindow{public:    HWND Handle( ) const;protected:    HWND mHandle;};NOTE: Generally it is a bad idea to provide accessors (and even worse mutators) to 'handles', but since libraries such as those found in the DirectX SDK and others require access to it, this is imo the easiest/best way to handle it.In the snippet above we can see a base window class that posesses a protected handle, now handles are usually dealt with internally so it makes sense for it to be protected/private as not for clients to modify thier value and helps avoid lengthy debugging sessions. Having mHandle public would allow you to get the handle but also set it which is a big no-no.Its all about making that distinction between what should/shouldnt be accessed or mutated, there are plenty of loop holes in this and as I said before personal preference plays some part. So its pretty much a grey area, but when in doubt you should "prefer private to public member variables" - I forgot what book thats fromNothing is written in stone (i.e. You MUST do this, at this SPECIFIC time), just try to learn and grow..[/source]   ;  You should attempt to combine data and operations related to it inside the same classes.If you only need to clamp up some related variables, you could as well use a struct.For the "visibility problem" with classes, you can use the "friend" keyword to provide exception in encapsulation. IMHO. Doing a direct port from C to C++ is a bit pointless. The greatest benefit from C++ specific features comes from the high-level design choices it allows you to make. Inheritance, polymorphism and templates. All aimed at reducing redundancy in exchange for a bit more computational cost.Otherwise you will just have a slightly more computationally expensive structs.( Namely the constructors and destructors)And yes, neither am I a C++ "certified" person. This however is the picture I have parsed from the books and practical studies with the language.[Edited by - rmed002 on May 21, 2010 2:19:59 PM];  rmed002:I never got as far as constructors or destructors in C, I think I hardly had any structs either, certainly not with member functions (they can have member functions? :)  It actually wasn't a direct port.  I re-coded everything from scratch, switched APIs (GLUT to SDL), so it could only really be said this is the same program in that it generates terrain and renders with OpenGL, but all the algos are different.  I'm intrigued to go back and look at how data structures are handled in C though to see if there's any performance to be gained.CodeCriminal:Thanks. The concepts of 'accessors' and 'mutators' is new to me I'll have to look it up.  The handle example is kind of mystical to me, I haven't had to deal with windows API.  What does a handle object usually contain, a pointer to another object?Also inheritence goes along with polymorphism right?  That is, derived classes 'inherit' the member variables?(It will be useful when I start adding more game-type objects, I actually had some polymorphic classes that were removed somewhere along the line as I've just been working on the geometry clipmaps for a while)   ;  The most important principle with OOP is the encapsulation of data and functions. When making many variables public, or providing getters and setters for them you are not actually keeping the variables and the functions that deal with them together.The trick is to find each bit of code that does access the members of some class, and see how you can make that function, or at least part of it into a function that belongs in the class where the data is.It can get a little harder than that since your code may have to deal with multiple objects and that's where friend sometimes comes in, but often the code has one main object it is associated with, and the other things it requires can just be passed in.If you post some of the code that touches the variables from the classes you posted then we can help you turn those into member functions.Also, try and pass const references rather than non-const references wherever possible.   ;Quote:Original post by iMalcIf you post some of the code that touches the variables from the classes you posted then we can help you turn those into member functions.Also, try and pass const references rather than non-const references wherever possible.Okay, here comes the stupid question of the day...How exactly does const DataType &ref  = *whatever;differ from  DataType &ref = *whatever;in practise?Since references are immutable by their very nature, you cannot rebind them.And since the const is affecting the reference variable, not the target object in memory, Im not sure what the point is?   ;Quote:Original post by rmed002Since references are immutable by their very nature, you cannot rebind them.And since the const is affecting the reference variable, not the target object in memory, Im not sure what the point is?You cannot rebind them, but you can still change the data members.struct DataType{    int x;};const DataType &ref1  = *whatever;ref1.x = 5; // WRRRRRONG!DataType &ref2  = *whatever;ref2.x = 5; // sure, that is fineBtw, I'm not 100% familiar with reference reseating, but this seems to work:struct DataType{    int a;};int main(){    DataType a;    DataType b;    DataType &x = a;    x = b;    return 0;}EDIT: of course it works, I do assignment here...lol[Edited by - Decrius on May 22, 2010 2:13:13 AM];  Looking at disassembly, references are pointers are passed the same way through the opcodes. It's going to end up a grammar/syntax difference more than an execution difference.   ;Quote:Original post by rmed002And since the const is affecting the reference variable, not the target objectWrong. T& is a reference to a T which you can mutate through the reference, whereas const T& is a reference to a T which you CANNOT mutate through the reference. The reference itself is always "const" and is not affected by that.   ;Quote:Original post by rmed002Since references are immutable by their very nature, you cannot rebind them.A "const reference" does not mean a reference which is itself constant; that is, as you point out, redundant. (It would be spelled "Foo& const" in C++.) Instead, we mean a reference to a thing which is constant, as viewed via that reference. I.e. either 'const Foo&' or 'Foo const&', which (perhaps confusingly) mean exactly the same thing. (The problem with the syntax is that if you have a basic type name and (N - 1) *'s and &'s - thus N things in total - then there are N aspects of the type that could be constant, but N + 1 places to put the word 'const'. In C++, the first two are equivalent.)Quote:And since the const is affecting the reference variable, not the target object in memory, Im not sure what the point is?It is affecting the target object in memory. The type means "I promise not to modify the object when I access it through this reference".   