Archived

This topic is now archived and is closed to further replies.

SCRUB

defines v.s. enums

Recommended Posts

Heres a quick silly question , but Its something I want to ask as its bugging me. From looking at loads of source code say the q3 source its riddled with enums and #defines ... and the question strikes me as to when you would use an enum instead of a #define when they basically are the same thing and used much the same way (or vise versa) e.g. typedef enum { CON_DISCONNECTED, CON_CONNECTING, CON_CONNECTED } clientConnected_t; it doesnt make sence to me as clientConnected_t isnt used anywhere and the values are just 0 1 2 etc which is exactly like a group of #define''s p.s. is _t mean type and _s system ? any documents on this type of notation ? p.s. sorry for the boggy questions but they are irritating me.

Share this post


Link to post
Share on other sites
In C++ you no longer require the typedef on enums, just like you no longer require them on structs. Using enum declares a type, not just a series of variables:
enum EnumeratedIdentifier { id_zero = 0, id_one, id_two, id_four = 4, id_five };
.
int ManipulateObjectByID(Object &obj, EnumeratedIdentifier id);

Note the use of ''EnumeratedIdentifier'' as a type, just like a class/struct/intrinsic type. You can''t do that with a #define. Also, note the id_four = 4. It lets me change the starting sequence (so I can have multiple identifiers with the same value) in a very convenient way. If you wanted to declare 30 identifiers, would you rather type
#define id_one 1
#define id_two 2
#define id_three 3
.
.
#define id_thirty 30

or
enum ids { id_one = 1, id_two, id_three, ..., id_thirty }; 

?

Having enums behave as intrinsic types enforces type-checking, which is A Good ThingTM.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
enum and #define are totally different (even though it may appear they serve the same purpose).

A #define PI 3.1415 instructs the compiler to replace a PI with 3.1415 anywhere in the code.

An enum is different. If you had an enum like this:
enum STATUS {CONTINUE=1, QUIT, WIN, LOST};

You could have done this with #defines too but, this is nicer, and it promotes type-checking.
With CONTINUE = 1, QUIT = 2, WIN = 3, LOST = 4;


You have just created a user-defined type (#defines aren't this). So it sort of acts like a struct (at least in the way you instantiate it). So in order to access this user-defined type you would do something like this.

    
int main()
{
// Instantiate the enumerated structure

STATUS gStatus;
char ans;

cout << "Play (y or n):\t";
cin >> ans;

if(toupper(ans) == 'Y')
gStatus = CONTINUE;
else
gStatus = QUIT;

while(gStatus == CONTINUE)
{
// Do whatcha want

if(gStatus == WIN)
{
cout << "YOU WIN";
gStatus = QUIT;
}
else if(gStatus == LOST)
{
cout << "LOSER, with a capital L (and OSER)!";
gStatus = QUIT;
}
}

cout << "Why leave so soon?";
}


Ok, well that was something I just came up with in a minute or two. Do you see why enum is different. You could do the same thing with #define but that would get too messy; this is more clearer and concise for this purpose.

Also, the identifiers (i.e. WIN, LOST) need to be unique. So, they are just #defines essentially, but it's a user-defined type. You could have multiple STATUS like this:

  
...
STATUS gameStatus;
STATUS alienStatus;
STATUS humanoidStatus;
STATUS worldStatus;
..
// AND YOU CAN USE THE IDENTIFIERS INTERCHANGEABLY WITH THESE

gameStatus = CONTINUE;
alienStatus = LOST; // No more aliens I guess

humanoidStatus = WON;
worldStatus = QUIT;


Did I help. Hope so.

Good Luck!

Edited by - Floppy on December 12, 2001 9:19:45 PM

Share this post


Link to post
Share on other sites
You can also assign one of your enums to another. Borrowing Floppy''s example you could do this:
gameStatus = worldStatus; 

That is not possible with #defines.

Floppy raised another important point; #defines are preprocessor directives, meaning that they never make it into your actual compiled code. They get replaced with their value everywhere they occur before compilation, which can introduce many hard to track bugs. for this reason, C++ always encourages you to use inline functions instead of macro #defines, const instead of #defines for single variables and enums in other cases.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
quote:
Original post by Oluseyi
C++ always encourages you to use inline functions instead of macro #defines...

To add more: C99 compliant C compilers also support inline functions. So, if your C compiler is up-to-date (there is a real possibility that it isn't, unfortunetly) you can use inline functions in it too.

[Resist Windows XP's Invasive Production Activation Technology!]

Edited by - Null and Void on December 12, 2001 9:55:48 PM

Share this post


Link to post
Share on other sites