Thread: General questions about style, syntax and best practices.

  1. #1
    Registered User
    Join Date
    Jul 2012
    Posts
    23

    General questions about style, syntax and best practices.

    I recently finished an introductory course to c++ at my college. The course covered the basics, it started with variables, data types, control structures, functions and ended with a brief glimpse at structs.
    It didn't cover classes or any type of object oriented programming.

    After finishing the final project I was left with many questions about different general aspects that only emerged after having to deal with the real problem solving puzzle that the project itself represented.

    These are some of them, I was hoping one you guys could shed some light to them:



    1- variable scope: is it OK to declare variables in different sections of a function, where its use is pertinent, or must all function variables be global to that function. ?

    2- - Is it OK to use global constant variables to enlighten the meaning of function arguments, when calling that function. As opposed to using just numbers or values. ?
    e.g :
    Code:
     
    ...
    const bool VERBOSE = true;
    ...
    copyFiles(VERBOSE);
    
    instead of:     
    
    copyFiles(true);
    As the name implies, verbose makes copyFiles(); provide information of what it's doing.


    3- Where should default argument values be properly declared, in the function prototype or in the function definition. ?

    4- Code repetition: I am under the impression that repeating the same instruction over and over when different conditions are met, is inefficient and requires more typing work. So I try to avoid it. However I often find myself in situations where I waste much time trying to figure out how to restructure a whole section of code so I don't have to repeat a line many times.
    Besides wasting my time and calories, this distracts me from the general bigger picture of the program, and I lose valuable design ideas I had. Moreover, more often than not I end up with a half-assed solution that consists of using a variable if the condition is met, to trigger the line(s) of code that I would have to repeat.
    The problem is that I end up having to repeat the new line assigning the var to a certain value, as many times as before, plus, now I need to add a check for the variable to have that value, before triggering the previous line of code I wanted to avoid repeating in the first place. If there is just one line needing repetition, is it ok to go ahead and copy it if it can't be avoided, or is the solution depicted above still a better alternative ?

    e.g: Here is an excerpt of my final project were I encountered a similar situation,
    Code:
            if (someConditionIsMet)
            {   message ("g_over");
                game_over = true;
            }
            else if (someConditionIsMet)
            {   message ("noAmmo");
                game_over = true;
            }
            else if (someConditionIsMet)
            {   message ("ranAway");
                game_over = true;
            }
    
            if (game_over)
            {   message ("exit");
                initialize();
            }
    
    As opposed to:
    
            if (someConditionIsMet)
            {   message ("g_over");
                message ("exit");
                initialize();
            }
            else if (someConditionIsMet)
            {   message ("noAmmo");
                message ("exit");
                initialize();
            }
    
    Where I repeat message ("exit"); and  initialize(); over and over.
    Many thanks.
    Last edited by skyliner; 07-08-2012 at 01:48 AM. Reason: clarity

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    1. Yes.
    2. NO (well, it isn't that bad , but this is what macros were traditionally used for. Enums are a better solution for this kind of things, especially when there are more options than a boolean variable can hold.)
    3. Prototype and declaration are the same thing.
    4. Not sure what you want here, but you could do something similar (and simpler) with exception handling.
    Last edited by manasij7479; 07-08-2012 at 01:20 AM.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by skyliner
    1- variable scope: is it OK to declare variables in different sections of a function, where its use is pertinent, or must all function variables be global to that function. ?
    The former. The rule of thumb is to declare variables near first use.

    Quote Originally Posted by skyliner
    2- - Is it OK to use global constant variables to enlighten the meaning of function arguments, when calling that function. As opposed to using just numbers or values. ?
    Yes, it is good practice to avoid magic numbers and such. This constant should effectively be part of the interface of the function or the library at large, so it should say, be in the same namespace or declared as a static const member of the same class.

    That said, in your example the VERBOSE constant is overkill: it is the parameter that should be named verbose, then you just pass true to it. What would be appropriate for constants is if you have named verbosity levels, e.g., SILENT, QUIET, VERBOSE, or something like that. So instead of passing 0, 1, or 2, you pass these named constants.

    Quote Originally Posted by skyliner
    3- Where should default argument values be properly declared, in the function prototype or in the function declaration. ?
    In the function prototype so that callers can determine that providing an argument for that parameter is optional. Of course, this means that you must take care not to declare the function inconsistently, and to document the function definition.

    Quote Originally Posted by skyliner
    4- Code repetition: I am under the impression that repeating the same instruction over and over when different conditions are met, is inefficient and requires more typing work.
    It may or may not be efficient. It might require more typing, but generally having to type a little more is not a concern. What is a concern is if you are just repeating yourself, or if the code can be written in a more readable way.

    Quote Originally Posted by skyliner
    If there is just one line needing repetition, is it ok to go ahead and copy it if it can't be avoided, or is the solution depicted above still a better alternative ?
    You can always come back to your code to refactor it.

    Quote Originally Posted by skyliner
    Here is an excerpt of my final project were I encountered a similar situation
    Your code is fine.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Jul 2012
    Posts
    23
    Quote Originally Posted by manasij7479 View Post

    3. Prototype and declaration are the same thing.

    I meant definition. fixed it.

    Quote Originally Posted by manasij7479 View Post

    4. Not sure what you want here, but you could do something similar (and simpler) with exception handling.
    Edited OP to reflect my question with more clarity.

  5. #5
    Registered User
    Join Date
    Jul 2012
    Posts
    23
    Quote Originally Posted by laserlight View Post
    ....
    Thank you very much.

  6. #6
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    What I meant by using exception there:
    Code:
    //Simple exception class:
    class GameException //Inherit from some standard exception if required
    {
     public:
         GameException(const std::string& msg_,bool fatal_):msg(msg_),fatal(fatal_){};
         std::string what(){return msg;}
         bool isFatal(){return fatal;}
    private:
         std::string msg;
         bool fatal;
    };
    Code:
    //..Within some big loop
    try
    {
        if(foo_condition)
            throw(GameException("foo",false));
        else if (bar_condition)
            throw(GameException("bar",true));
    }
    catch(const GameException& ge)
    {
        std::cerr<<ge.what();
        if(ge.isFatal()){message("exit");initialize();}//or whatever..
    }
    P.S: I'm using a similar structure in a game I'm making... so if anyone finds something wrong with that design... virtual cookies.
    Last edited by manasij7479; 07-08-2012 at 02:23 AM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manasij7479
    What I meant by using exception there:
    Before the code example was edited, the examples I saw were for things like "out of life" or "out of ammo" conditions during the course of a game. If these were expected to happen at that point (e.g., the player merely exhausted his/her ammo supply by shooting too much) rather than errors (e.g., the player should not be out of ammo at that point), then throwing an exception would not be appropriate.

    Quote Originally Posted by manasij7479
    Inherit from some standard exception if required
    I think that exception classes should always inherit from std::exception, one of its subclasses, or some other designated exception base class. This way you can catch them using a handler for the base class.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by laserlight View Post
    Before the code example was edited, the examples I saw were for things like "out of life" or "out of ammo" conditions during the course of a game. If these were expected to happen at that point (e.g., the player merely exhausted his/her ammo supply by shooting too much) rather than errors (e.g., the player should not be out of ammo at that point), then throwing an exception would not be appropriate.
    Isn't that the point of exceptions?
    If the exception is just "Out of Ammo" or something that is expected to happen at some point,the catch block would show relevant errors, like making a hollow sound when a gun is fired and the OutOfAmmo is thrown, and then continue on the big loop as if nothing has changed.
    (The alternative would be to perform a lot of checks for every single thing, which could be slightly faster but very difficult to modify or extend, imho.)
    Last edited by manasij7479; 07-08-2012 at 02:49 AM.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manasij7479
    Isn't that the point of exceptions?
    Exceptions are for reporting errors so that they can be handled separately from normal processing.

    Quote Originally Posted by manasij7479
    If the exception is just "Out of Ammo" or something that is expected to happen at some point, he catch block would show relevant errors, like making a hollow sound when a gun is fired and the OutOfAmmo is thrown, and then continue on the big loop as if nothing has changed.
    If you write the code with the intention that the user can attempt to fire the gun when there is no ammo, and the user actually does that, then there is no error, so you should not be throwing an exception.

    Referring to Stroustrup's FAQ on How do I use exceptions?
    Quote Originally Posted by Bjarne Stroustrup
    Do not use exceptions as simply another way to return a value from a function. Most users assume - as the language definition encourages them to - that exception-handling code is error-handling code, and implementations are optimized to reflect that assumption.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    I'm not sure I understand.
    Quote Originally Posted by laserlight View Post
    Exceptions are for reporting errors so that they can be handled separately from normal processing.
    If you write the code with the intention that the user can attempt to fire the gun when there is no ammo, and the user actually does that, then there is no error, so you should not be throwing an exception.
    How is "I want to fire but have no ammo" not an error ?

    Referring to Stroustrup's FAQ on How do I use exceptions?
    I'm not talking about another way of returning values..
    I'm saying:
    This should really happen in this way (a projectile is thrown with a loud sound), but there is a problem (out of ammo), so lets do it differently (make a hollow sound, and perhaps some smoke comes out of the barrel!).

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manasij7479
    How is "I want to fire but have no ammo" not an error ?
    It depends on context. From within a function that states that there must be ammo to use as a pre-condition, it is an error. But from within a function that calls such a function, it could just be the normal state of affairs.

    Quote Originally Posted by manasij7479
    This should really happen in this way (a projectile is thrown with a loud sound), but there is a problem (out of ammo), so lets do it differently (make a hollow sound, and perhaps some smoke comes out of the barrel!).
    If you are writing a function to throw the projectile with a loud sound, then yeah, throwing an exception if there is no ammo makes sense. If you are writing the function that calls that, then you could use the notion that "it is easier to ask forgiveness than permission" by catching the exception, but that notion is not the norm in C++ with respect to exception handling. The norm would be to check the condition (have ammo vs no ammo) and then react accordingly, since in that context "no ammo" is not an error.

    EDIT:
    Come to think about it, that "function to throw the projectile with a loud sound" may well be just a helper function for which an assertion should be used instead. But I guess this is again a matter of "it depends".
    Last edited by laserlight; 07-08-2012 at 03:46 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by laserlight View Post
    If you are writing a function to throw the projectile with a loud sound, then yeah, throwing an exception if there is no ammo makes sense. If you are writing the function that calls that, then you could use the notion that "it is easier to ask forgiveness than permission" by catching the exception, but that notion is not the norm in C++ with respect to exception handling. The norm would be to check the condition (have ammo vs no ammo) and then react accordingly, since in that context "no ammo" is not an error.
    But things are seldom so 'boolean' !

    Say, the player clicks the mouse -> The Event Handler conveys to the gun that it needs to be fired -> The gun can agree, creating a child projectile and telling the scene manager what to do with it ... or it can throw a variety of exceptions (say.. OutOfAmmo, Damaged, SafetyLatchOn, etc), the outer loop then catches the exception as a base class object and decides what to do with it, looking up in a predefined dictionary of functions, which have almost nothing to do with the gun itself.
    (I could come up with many more mishaps, if this was a vehicle and not a gun ! :P )

    Doing this with many if-else checks will be messy, I think.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manasij7479
    Doing this with many if-else checks will be messy, I think.
    At some point you are going to have the if-else checks to determine what exception to throw.

    Quote Originally Posted by manasij7479
    The gun can agree, creating a child projectile and telling the scene manager what to do with it ... or it can throw a variety of exceptions (say.. OutOfAmmo, Damaged, SafetyLatchOn, etc)
    You need to catch all the specific exceptions since allowing the exception to propagate does not make sense (hence it behaves much like a return value). You could catch the base class exception, but it does not make sense since you want to perform a specific action, not report/log an error and try to recover.

    Quote Originally Posted by manasij7479
    the outer loop then catches the exception as a base class object and decides what to do with it, looking up in a predefined dictionary of functions, which have almost nothing to do with the gun itself.
    Then a better design is for the function to return a function (object) that can be called in the outer loop.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Say, the player clicks the mouse -> The Event Handler conveys to the gun that it needs to be fired -> The gun can agree, creating a child projectile and telling the scene manager what to do with it ... or it can throw a variety of exceptions (say.. OutOfAmmo, Damaged, SafetyLatchOn, etc), the outer loop then catches the exception as a base class object and decides what to do with it, looking up in a predefined dictionary of functions, which have almost nothing to do with the gun itself.
    O_o

    Doing this with many if-else checks will be messy, I think.
    o_O

    You can't avoid those checks.

    You've deliberately created a situation where examining an exception is the requirement in order to give reasonable feedback.

    These situations that you've deemed worthy of an exception are going to be common events by virtue of their totally normal occurrence.

    In a big shooter, do you always check if you have ammo before pulling the trigger?

    What this means is, you'll have to transform this common event into an exception. That transformation requires checks. Example:

    Code:
    class IGun;
    // ...
    void IGun::Fire()
    {
        // ...
        if(!mAmmo)
        {
            throw(OutOfAmmo());
        }
        // ...
        if(!mRepair)
        {
            throw(Damaged());
        }
        // ...
        if(!mSafety)
        {
            throw(SafetyLatchOn());
        }
        // ...
    }
    That only tells us half the story. Checks are needed higher in the engine. Example:

    Code:
    class IEngine;
    // ...
    void IEngine::handleEvent
    (
        int fEvendID
    )
    {
        // ...
        // handle other events
        // ...
        if(fEvendID == mWeaponFire)
        {
            try
            {
                getPlayerGun()->Fire();
            }
            catch(const OutOfAmmo &)
            {
                // code to trigger "dry fire" sound
            }
            catch(const Damaged &)
            {
                // code to trigger "force discard weapon"
            }
            catch(const SafetyLatchOn &)
            {
                // code to trigger "bolt catch" sound
            }
        }
        // ...
        // handle other events
        // ...
    }
    All attempts that would simplify the code will also work as implemented with callbacks, returning objects, and simple conditional codes. Example:

    Code:
        // if this code works conceptually
        // ...
        if(fEvendID == mWeaponFire)
        {
            try
            {
                getPlayerGun()->Fire();
            }
            catch(const IGunException &)
            {
                GunExceptionTable[IGunException()->mID](*this, getPlayerGun());
            }
        }
        // ...
        // so does this
        // ...
        if(fEvendID == mWeaponFire)
        {
            if(int sID = getPlayerGun()->Fire())
            {
                GunExceptionTable[sID](*this, getPlayerGun());
            )
        }
        // ...
        // and this
        // ...
        if(fEvendID == mWeaponFire)
        {
            getPlayerGun()->Fire(*this); // uses table directly
        }
        // ...
    In other words, here the use of the exception mechanism has bought you exactly nothing.

    Soma

  15. #15
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    I see!
    I was just a few layers of abstraction off.. .

    So, what I gathered from this thread: "Avoid exceptions unless the problem is 'somewhat' irrecoverable". Right ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. [General Help] Dynamic Arrays and General Pointer syntax
    By Amberlampz in forum C Programming
    Replies: 22
    Last Post: 07-26-2011, 10:58 PM
  2. Beginner question about understanding general Syntax
    By lucidrave in forum C++ Programming
    Replies: 15
    Last Post: 08-13-2009, 03:57 PM
  3. A Few General C Questions
    By Jedijacob in forum C Programming
    Replies: 13
    Last Post: 02-17-2005, 02:47 AM
  4. Syntax Style
    By darfader in forum C Programming
    Replies: 2
    Last Post: 10-03-2003, 05:21 AM
  5. General Dev Questions
    By drdroid in forum C++ Programming
    Replies: 1
    Last Post: 09-11-2002, 08:06 PM