terloon
|
|
« Reply #60 on: February 28, 2010, 09:13:04 PM » |
|
#defines are like global search and replace and really should have no place in c++. enums give you data encapsulation and type checking.
|
|
|
Logged
|
|
|
|
Glaiel-Gamer
Guest
|
|
« Reply #61 on: February 28, 2010, 10:30:21 PM » |
|
I don't see any benefits of using enums instead of good old defines.
embed an enum in a struct struct ColorChannelMask { enum { RED = 0xFF000000, BLUE = 0x0000FF00, GREEN = 0x00FF0000, ALPHA = 0x000000FF }; };
Now, unlike a define, the values are relative to the struct ColorChannelMask::RED ColorChannelMask::GREEN ColorChannelMask::BLUE ColorChannelMask::ALPHA
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #62 on: February 28, 2010, 11:36:59 PM » |
|
I don't see any benefits of using enums instead of good old defines.
embed an enum in a struct struct ColorChannelMask { enum { RED = 0xFF000000, BLUE = 0x0000FF00, GREEN = 0x00FF0000, ALPHA = 0x000000FF }; };
Now, unlike a define, the values are relative to the struct ColorChannelMask::RED ColorChannelMask::GREEN ColorChannelMask::BLUE ColorChannelMask::ALPHA Even better, the new C++ standard provides scoped enums via "enum class" enum class DayOfWeek {monday, tuesday, ...etc};
DayOfWeek today = DayOfWeek::sunday;
|
|
|
Logged
|
What would John Carmack do?
|
|
|
Fallsburg
|
|
« Reply #63 on: March 01, 2010, 08:03:20 AM » |
|
//I prefer to use #pragma once //Instead of #ifndef MY_HEADER_H #define MY_HEADER_H #endif // Mostly because I am completely anal and am afraid that I am going to step on someone else's #define // and while I know that #pragma once is compiler dependent, I am not so concerned with portability
//I prefer curly brackets as follows for (int ii = 0; ii < 10; ii++){ } //And I don't use single letter variables (i,j,k,etc.) but instead use double letters //as it makes it much easier to find/replace operations on the variables
//I only do trivial definitions in header files, i.e. nothing beyond a get/set method class MyClass{ public: int getVar(){ return var; } void setVar(int var_){ var = var_; } private: int var; };
// I only capitalize user defined data structures (classes, enums, structs,etc.) // In a physics setting, if the units of something are not in SI units, // I will specify the units at the end of the variable name double myMass; //Assumed to be kg double myStupidMass_slug; //Honestly, why would you ever use slugs?
|
|
« Last Edit: December 18, 2015, 05:08:37 PM by Silbereisen »
|
Logged
|
|
|
|
Mikademus
|
|
« Reply #64 on: March 01, 2010, 08:26:00 AM » |
|
//I prefer to use #pragma once //Instead of #ifndef MY_HEADER_H #define MY_HEADER_H #endif
Have you tried compiling that on a compiler not MSVC?
|
|
|
Logged
|
\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
|
|
|
Kadoba
|
|
« Reply #65 on: March 01, 2010, 09:01:40 AM » |
|
Have you tried compiling that on a compiler not MSVC?
I know it also works with GCC but it's considered depreciated. I use to use "#pragma once" exclusively but I've heard a lot of arguments against it. So now I risk straining myself by adding two extra lines.
|
|
|
Logged
|
|
|
|
Sos
|
|
« Reply #66 on: March 01, 2010, 10:33:56 AM » |
|
Yeah, #pragma is compiler specific, but it's safe unless you plan portability.
also: I hate errors like "expected const char*, but got char **, there is no possibility of cast there" or sth like this in MSVC particularily. this example might not give the error, but I got many like these from stuffing regular types, where GL* were expected. AAAAnd, that's why I don't use enums.
|
|
|
Logged
|
|
|
|
LemonScented
|
|
« Reply #67 on: March 01, 2010, 10:56:21 AM » |
|
All caps enum (and const) values are another thing that can be very dangerous, since it's just begging for macro clashes. I think this comes from the fact that enums and const were relatively late additions to C, and I think people used to convert #define macros without the changing the names. It's the only explanation I can come up with for why people do this.
It's worth noting than modern C++ authorities like Stroustrup all recommend against doing this.
My coding style tends to be shaped by things that have bitten me in the ass before, and the enum thing is something that's never been a problem for me. That said, I tend to (as in my example) declare enums inside the classes they're relevant to, so it's not often I have one in the global namespace anyway. With that being the case, having an all caps convention for anything that's constant (const variables, #defines and enums) is a good way to identify something as being a value that can't be changed.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #68 on: March 01, 2010, 12:17:53 PM » |
|
That said, I tend to (as in my example) declare enums inside the classes they're relevant to, so it's not often I have one in the global namespace anyway. Macros don't care about scopes and namespaces, that's no protection. With that being the case, having an all caps convention for anything that's constant (const variables, #defines and enums) is a good way to identify something as being a value that can't be changed.
Why do you need to identify this? The compiler won't let you change them anyway.
|
|
|
Logged
|
What would John Carmack do?
|
|
|
skyy
|
|
« Reply #69 on: March 01, 2010, 01:19:38 PM » |
|
Why do you need to identify this? The compiler won't let you change them anyway.
But isn't that compile time? personally I'd like to know this before compiling and this way not waste compile time (yeah, those precious milliseconds...). So I'm guessing seeing them all caps is like: " a-ha.. I already know this is a constant, I cannot change it", instead of doing the same thing once the compiler starts crying about it during compile and THEN changing the variable/constant/what ever you are working on that caused the problem and re-compile. Did I even hit close LemonScented? But yeah, macros really do not care about scopes or namespaces, it's all open warzone for those babies. When I'm doing C++, I only tend to use macros inside .cpp files ... Not the best solution but sometimes I just love having macros. Cannot help it. I guess it's the nostalgy from good old C and being punched in the face..? Who knows.
|
|
|
Logged
|
|
|
|
Fallsburg
|
|
« Reply #70 on: March 01, 2010, 01:23:41 PM » |
|
Have you tried compiling that on a compiler not MSVC?
I know it also works with GCC but it's considered depreciated. I use to use "#pragma once" exclusively but I've heard a lot of arguments against it. So now I risk straining myself by adding two extra lines. Yeah, I have with GCC. But I use the #defines as well, just to be extra safe.
|
|
|
Logged
|
|
|
|
LemonScented
|
|
« Reply #71 on: March 01, 2010, 02:57:17 PM » |
|
@skyy: Yes, you've pretty much got it. If you're going to get super-cautious about the possibility of macros trampling all over stuff, there's additional spookiness in the fact that there's nothing to stop macros containing lowercase characters anyway, so in theory they post a risk right across the board, not just to things with uppercase names. In practise, it's not something that's ever bitten me, so I don't tend to lose sleep over it - I knowingly do a lot of things in my coding style which are potentially risky, but I figure if I'm aware of the risks, and consider the benefits of my approach to outweigh them, it's all good. For instance this: if(SOME_CONSTANT == someVariable) is safer than this: if(someVariable == SOME_CONSTANT) but the former just reads all backwards, which is why I don't use it - I just crank up the warning level to maximum, treat warnings as errors, and let the compiler catch it that way. Of course, as I said, you should really prefer const int over #define, but I don't (because the syntax colouring in my IDE picks out #defines better, so the constants are easier to see, and again I like my code as quick to read and comprehend as poosible). But either way, it's good practise in general to keep consts or #defines (or pretty much anything else for that matter) as closely-scoped and descriptively-named as possible, and to avoid libraries with poorly-named and scoped elements which might clash with your own.
|
|
|
Logged
|
|
|
|
jotapeh
|
|
« Reply #72 on: March 01, 2010, 08:23:41 PM » |
|
For instance this: if(SOME_CONSTANT == someVariable) is safer than this: if(someVariable == SOME_CONSTANT) Yeah. I actually first saw this when perusing metanet's N source code for collisions. It really confused me when I saw < and > signs, with the literal on the left-hand side.. I'm not sure why it reads so poorly (it's still logically correct), but you are right that it is awkward
|
|
|
Logged
|
|
|
|
Glaiel-Gamer
Guest
|
|
« Reply #73 on: March 01, 2010, 08:59:47 PM » |
|
For instance this: if(SOME_CONSTANT == someVariable) is safer than this: if(someVariable == SOME_CONSTANT) Yeah. I actually first saw this when perusing metanet's N source code for collisions. It really confused me when I saw < and > signs, with the literal on the left-hand side.. I'm not sure why it reads so poorly (it's still logically correct), but you are right that it is awkward It's cause like, in english, you're going to ask yourself "Do I have greater than 4 eggs?", not "Is 4 less than the number of eggs I have?". Even though both sentences are "correct", one is easy to understand and the other is yoda-talk. Also, the only reason the first form is "safer" is "just in case" you type 1 equals sign instead of 2. It'll still compile and run, but you'll get unexpected results. If the constant comes first, 4=variable is a compile-time error. It's dumb though, I don't write my code to plan for tiny mistakes like that, those are the easiest to find and fix. The hard ones are when your code isn't readable in english, and you need to go through and go "ok so if 4 is less than speed and (there is a collision on the ground but not in the water+20pixels) or there's a collision in the water-20 pixels, and (timer is less than 0 and there is a timer) or there is no timer and... wait I lost track"
|
|
« Last Edit: March 01, 2010, 09:03:00 PM by Glaiel-Gamer »
|
Logged
|
|
|
|
Glaiel-Gamer
Guest
|
|
« Reply #74 on: March 01, 2010, 09:16:12 PM » |
|
"ok so if 4 is less than speed and (there is a collision on the ground but not in the water+20pixels) or there's a collision in the water-20 pixels, and (timer is less than 0 and there is a timer) or there is no timer and... wait I lost track"
Also this tends to happen to a lot of my logic code, and I usually deal with it until it REALLY pisses me off. For instance, in Closure, the logic for dropping an orb was as follows: if the character is grounded, and the orb is not in a no drop zone, and the orb is not colliding with the ground, and the key is pressed, then drop the orb it was a long block of code, duplicated a few times here and there for pedestals later I needed to change the behavior of an orb to if the character is grounded and the key is pressed and the orb is not in a no drop zone, and either the orb is unlit OR the (orb is lit and the orb is not in the ground) duplicated of course for some sound effects, slightly modified. Became super sphaghetti-y, so I've started putting those types of tests into "verb-able" functions so the orb has a function "droppable", "pickupable", and the door has a function for "openable", etc. Makes it super so much easier to read when I can look at the code and read "if the character is grounded, the key is pressed, and the orb is droppable, then drop the orb", rather than a mess of shit
|
|
|
Logged
|
|
|
|
Sos
|
|
« Reply #75 on: March 01, 2010, 11:04:02 PM » |
|
I don't narrate my code. Anyways, I can speak ANSI C, so I don't need to.
|
|
|
Logged
|
|
|
|
shrimp
|
|
« Reply #76 on: March 02, 2010, 01:38:50 AM » |
|
I worked with a guy once who used arbitrary numbers for switch cases, e.g.
switch(x) { case 2: // something break; case 3: // something break; case 75: // something break; case 1010101101: // something break; }
With the accompanying x = 75, x = 10100101101 etc through the code.
Also his keys/hotkeys were mapped completely uniquely, so if anyone else on the team had to do something with his code on his machine whilst he was away (say, the day before a deadline) it looked like they were getting a sequence of strong electric shocks whenever they looked at the screen or touched the keyboard.
|
|
|
Logged
|
|
|
|
skyy
|
|
« Reply #77 on: March 02, 2010, 02:26:02 AM » |
|
Also his keys/hotkeys were mapped completely uniquely, so if anyone else on the team had to do something with his code on his machine whilst he was away (say, the day before a deadline) it looked like they were getting a sequence of strong electric shocks whenever they looked at the screen or touched the keyboard.
There are still people like this? Oh wow...
|
|
|
Logged
|
|
|
|
st33d
Guest
|
|
« Reply #78 on: March 02, 2010, 02:59:19 AM » |
|
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #79 on: March 02, 2010, 05:49:27 AM » |
|
I worked with a guy once who used arbitrary numbers for switch cases, e.g.
switch(x) { case 2: // something break; case 3: // something break; case 75: // something break; case 1010101101: // something break; }
With the accompanying x = 75, x = 10100101101 etc through the code.
This can be annoying, but I've also seen people take this way too far in the other direction, basically trying to never use a raw value. Sometimes a number really is just a number.
|
|
|
Logged
|
What would John Carmack do?
|
|
|
|