Search

6.x — Chapter 6 summary and quiz

Quick review

We covered a lot of material in this chapter. Good job, you’re doing great!

A compound statement or block is a group of zero or more statements that is treated by the compiler as if it were a single statement. Blocks begin with a { symbol and end with a } symbol, with the statements to be executed placed in between. Blocks can be used anywhere a single statement is allowed. No semicolon is needed at the end of a block. Blocks are often used in conjunction with if statements to execute multiple statements.

User-defined namespaces are namespaces that are defined by you for your own declarations. Namespaces provided by C++ (such as the global namespace) or by libraries (such as namespace std) are not considered user-defined namespaces.

You can access a declaration in a namespace via the scope resolution operator (::). The scope resolution operator tells the compiler that the identifier specified by the right-hand operand should be looked for in the scope of the left-hand operand. If no left-hand operand is provided, the global namespace is assumed.

Local variables are variables defined within a function (including function parameters). Local variables have block scope, meaning they are in-scope from their point of definition to the end of the block they are defined within. Local variables have automatic storage duration, meaning they are created at the point of definition and destroyed at the end of the block they are defined in.

A name declared in a nested block can shadow or name hide an identically named variable in an outer block. This should be avoided.

Global variables are variables defined outside of a function. Global variables have file scope, which means they are visible from the point of declaration until the end of the file in which they are declared. Global variables have static duration, which means they are created when the program starts, and destroyed when it ends. Avoid dynamic initialization of static variables whenever possible.

An identifier’s linkage determines whether other declarations of that name refer to the same object or not. Local variables have no linkage. Identifiers with internal linkage can be seen and used within a single file, but it is not accessible from other files. Identifiers with external linkage can be seen and used both from the file in which it is defined, and from other code files (via a forward declaration).

Avoid non-const global variables whenever possible. Const globals are generally seen as acceptable. Use inline variables for global constants if your compiler is C++17 capable.

Local variables can be given static duration via the static keyword.

Using statements (including using declarations and using directives) can be used to avoid having to qualify identifiers with an explicit namespace. These should generally be avoided.

Typedefs and Type aliases allow the programmer to create an alias for a data type. These aliases work identically to the aliased type. They can add legibility and reduce maintenance to code.

The auto keyword has a number of uses. First, auto can be used to do type inference / type deduction, which will infer a variable’s type from its initializer. Auto can also be used as a function return type to have the compiler infer the function’s return type from the function’s return statements, though this should be avoided for normal functions. Auto is used as part of the trailing return syntax. And finally, as of C++20, auto provides a shortcut for creating function templates. For now, you’ll generally use it for type deduction purposes.

Implicit type conversion is performed whenever one data type is expected, but a different data type is supplied. If the compiler can figure out how to do the conversion between the two types, it will. If it doesn’t know how, then it will fail with a compile error. Numeric promotion (or widening) occurs when a value from one fundamental data type is converted to a value of a larger fundamental data type from the same family (e.g. a short to an int). Numeric conversion occurs when we convert a value from a larger to a smaller type (e.g. int to short), or between different type families (int to double). Conversions that could cause loss of data are called narrowing conversions.

Explicit type conversion is performed when the programmer explicitly requests conversion via a cast. A cast represents a request by the programmer to do an explicit type conversion. C++ supports 5 types of casts: C-style casts, static casts, const casts, dynamic casts, and reinterpret casts. Generally you should avoid C-style casts, const casts, and reinterpret casts. static_cast is used to convert a value from one type to a value of another type, and is by far the most used-cast in C++.

Finally, C++ supports unnamed namespaces, which implicitly treat all contents of the namespace as if it had internal linkage. C++ also supports inline namespaces, which provide some primitive versioning capabilities for namespaces.

Quiz time

Question #1

Fix the following program:

Show Solution

Question #2

Write a file named constants.h that makes the following program run. If your compiler is C++17 capable, use inline constexpr variables. Otherwise, use normal constexpr variables. You can pick any value you like for max_class_size.

main.cpp:

Show Solution

Question #3

Complete the following program by writing the passOrFail() function, which should return true for the first 3 calls, and false thereafter.

Show Hint

The program should produce the following output:

User #1: Pass
User #2: Pass
User #3: Pass
User #4: Fail
User #5: Fail

Show Solution


S.4.4b -- An introduction to std::string
Index
6.17 -- Unnamed and inline namespaces

295 comments to 6.x — Chapter 6 summary and quiz

  • Brett

    No worries Alex, it would be nice if it did, but I think you are right and it can't. I found a few others with similar questions in the forums, but seems like its not a feature they have implemented yet.
    Thanks,
    Brett.

  • Brett

    Hi Alex,
    I am using CodeBlocks 16.01. When I type in  the code below (as part of the program), only "void" is highlighted in the code ,is there a way to make it appear as it does in your code examples?  it makes it more obvious which words are structs or classes.

    void printMonster(Monster monster) <----- both Monster and monster appear as "normal" text in my codeblocks screen.

    Thanks for the great lessons,
    Brett.

  • Kristoffer Fagerbekk

    Sorry to intrude. I am new in C++, and I found this task quite hard (Not so wierd maybe since I barely have been here), but I would really appreciate if someone tried to deeply explain how the example above works. I just cant get my head around some parts.

    • Alex

      Hi Kristoffer. Your request is a both broad and a bit vague -- can you be more specific about which things you're struggling to understand?

  • James

    Hi Alex,

    Thanks for a great tutorial. I really appreciate the rigour in your approach.

    Regarding the quiz question; I wanted to add a unique ID to each of my monsters and, recalling your discussion of static duration variables in section 4.3, used a function similar to generateID (monsterID in the below). When I instantiate (correct usage?) a monster, I use non-static member initialisation to assign the value returned by monsterID to Monster::id, a const int.

    I have three questions at this point:
    Is it proper to use non-static member initialisation for some members, and not others?
    Is it proper to use a non-static member initialisation that calls a function?
    For structs, you advise using uniform initialisation instead of non-static member initialisation in C++11. You note that mixing is possible in C++14, but don't discuss the ethics of this practice - what is your stance?

    Best,
    James

    My code:

    • Alex

      Great questions!

      > Is it proper to use non-static member initialisation for some members, and not others?

      Yes. Your use of non-static member initialization here is totally appropriate since the initialization value of the member doesn't vary per constructor.

      > Is it proper to use a non-static member initialisation that calls a function?

      Yes, but with one caveat. You should only call globally scoped functions (like monsterID() is) or static member functions (which we'll cover once we discuss classes). Calling normal member functions is asking for trouble. But you're fine here.

      > For structs, you advise using uniform initialisation instead of non-static member initialisation in C++11. You note that mixing is possible in C++14, but don’t discuss the ethics of this practice - what is your stance?

      Mixing is not only fine, it's a good idea, as it will ensure your struct members are always initialized while also allowing you to assign your own initialization values as appropriate. I've made a note of such in the lesson.

  • Matt

    In the sentence you updated(3rd paragraph), you forgot to rewrite the second half of the sentence (it still references the old phrasing).

  • Matt

    The third paragraph needs an update(local variables created at definition).

  • reznov

    Written it to be somewhat functioning as a game. So you tell the game your character level (where you left off last time I guess). Then it will match a monster to your level and you can choose to fight or run. If you fight you will win because there's no RNG functions in my toolkit yet and you will gain a level of experience. This will prompt a next fight request after every fight until eventually updating the monster type when you pass the required level or if you choose to run.

    This program raised a new question about structs however.. How can I build this program in a way I only have to only pass 1 variable to my function and still be able to read out the monster stats like slime.type ? I tried nesting structs but it didn't do much good :\

    #include <iostream>

    struct MonsterStats
    {
        std::string type;
        std::string name;
        int health;
        int level;
    };

    void printMonster(MonsterStats slime, MonsterStats spider, MonsterStats orc, MonsterStats ogre, MonsterStats dragon, int charLevel)
    {

        if(charLevel>=slime.level&&charLevel<spider.level)
            std::cout << "This " << slime.type << " is named " << slime.name << " and has " << slime.health << " health.\n";
        else if(charLevel>=spider.level&&charLevel<orc.level)
            std::cout << "This " << spider.type << " is named " << spider.name << " and has " << spider.health << " health.\n";
        else if(charLevel>=orc.level&&charLevel<ogre.level)
            std::cout << "This " << orc.type << " is named " << orc.name << " and has " << orc.health << " health.\n";
        else if(charLevel>=ogre.level&&charLevel<dragon.level)
            std::cout << "This " << ogre.type << " is named " << ogre.name << " and has " << ogre.health << " health.\n";
        else if(charLevel>=dragon.level)
            std::cout << "This " << dragon.type << " is named " << dragon.name << " and has " << dragon.health << " health.\n";
    }

    int main()
    {
        using namespace std;

        MonsterStats ogre{"Ogre","Grumble",345, 16};            //Type, Name, Health, Level
        MonsterStats dragon{"Dragon","Spyro", 890, 21};         //Type, Name, Health, Level
        MonsterStats orc{"Orc","Rakanishu", 165, 11};           //Type, Name, Health, Level
        MonsterStats spider{"Giant Spider", "Arachnid", 80, 6}; //Type, Name, Health, Level
        MonsterStats slime{"Slime", "Blurp", 35, 1};            //Type, Name, Health, Level

        std::string getChoice="y";
        int charLevel;
        cout << "Please enter the level of your character to proceed to battle: ";
        cin >> charLevel;
        if(charLevel>0)
        {
            while(getChoice=="y")
            {
                printMonster(slime, spider, orc, ogre, dragon, charLevel);

                cout << "Do you want to fight the monster? (y/n)";
                cin >> getChoice;
                if(getChoice=="y")
                {
                    cout << "You destroyed the monster and gained an experience level!\n\n";
                    charLevel+=1;
                }
                else
                    cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
            }
        }
        else
            cout << "Please create a character in order to play the game.";
        return 0;
    }

    • Alex

      Your program is organized a little strangely. I think you should do the following:
      1) Create a new function named generateMonster
      2) generateMonster should only take charLevel as a parameter, and return a monsterStats.
      3) Move the MonsterStats variables at the top of main() into generateMonster().
      4) generateMonster can do the same logic to determine what monster to return to main().
      5) modify printMonster to take a MonsterStats parameter and print out the stats for just that one monster passed in
      6) main() can call generateMonster() to return a monster of the appropriate type based on level, and printMonster() to print the monster's stats.

      This will be much more modular than what you have.

      • reznov

        Great! Thanks :)
        I've always been informed through our beloved programmers on stack overflow that later in this tutorial I will learn to do MonsterStats by array that can be editted with a loop and replace the infinite if else logic with some kind of a std::sort operator and some pointers. So definately something to look into for me in the later chapters to maybe actually turn this into some proper coded minigame :)

        So far the code looks like this after your advice, still working and lengty in code but finally rid of the long function parameter:

        #include <iostream>

        struct MonsterStats
        {
            std::string type;
            std::string name;
            int health;
            int level;
        };

        MonsterStats generateMonster(int charLevel)
        {
            MonsterStats ogre{"Ogre","Grumble",345, 16};            //Type, Name, Health, Level
            MonsterStats dragon{"Dragon","Spyro", 890, 21};         //Type, Name, Health, Level
            MonsterStats orc{"Orc","Rakanishu", 165, 11};           //Type, Name, Health, Level
            MonsterStats spider{"Giant Spider", "Arachnid", 80, 6}; //Type, Name, Health, Level
            MonsterStats slime{"Slime", "Blurp", 35, 1};            //Type, Name, Health, Level
            MonsterStats error{"","",0,0};

            if(charLevel>=slime.level&&charLevel<spider.level)
                return slime;
            else if(charLevel>=spider.level&&charLevel<orc.level)
                return spider;
            else if(charLevel>=orc.level&&charLevel<ogre.level)
                return orc;
            else if(charLevel>=ogre.level&&charLevel<dragon.level)
                return ogre;
            else if(charLevel>=dragon.level)
                return dragon;
            else
                std::cout << "Please create a character in order to play the game.";
                return error;
        }

        void printMonster(MonsterStats generated)
        {

            std::cout << "This " << generated.type << " is named " << generated.name << " and has " <<
            generated.health << " health.\n";

        }

        int main()
        {
            using namespace std;

            std::string getChoice="y";
            int charLevel;
            cout << "Please enter the level of your character to proceed to battle: ";
            cin >> charLevel;
            if(charLevel>0)
            {
                while(getChoice=="y")
                {
                    MonsterStats generated = generateMonster(charLevel);
                    printMonster(generated);
                    cout << "Do you want to fight the monster? (y/n)";
                    cin >> getChoice;
                    if(getChoice=="y")
                    {
                        cout << "You destroyed the monster and gained an experience level!\n\n";
                        charLevel+=1;
                    }
                    else
                        cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
                }
            }
            else
                cout << "Please create a character in order to play the game.";
            return 0;
        }

        As said in later chapters I will work on how lengthy it is with the advice I got from the guys and girls over at stackoverflow, they tend to go slightly out of scope of what I've learned.

        • reznov

          Oh whoops I did the error handling for charLevel<1 twice. Just the one in main should do since I don't expect the charLevel-incrementing while function to decrease it below 1 ever.

        • Alex

          Yup, next step is to move your monsters into an array and automatically iterate over the array. :) That will make your program more extensible, as you can add new monster by updating the array (no other code changes necessary).

  • Arturo Ortiz

    #include <iostream>

    using namespace std;

    struct MonsterStruc{

        string name;
        int health;

    };
    enum MonstersEnum{

        MONSTER_OGRE,
        MONSTER_DRAGON,
        MONSTER_ORC,
        MONSTER_GIANT_SPIDER,
        MONSTER_SLIME
    };

    string getMonster(MonstersEnum monsterE){

        if (monsterE == MONSTER_OGRE)
            return string("Ogre");
        if (monsterE == MONSTER_SLIME)
            return string("Slime");

    }
    void printMonster (MonsterStruc monster, MonstersEnum monster1 ){

        cout<< "This is an " << getMonster(monster1) << " his name is " << monster.name << " and his health is " << monster.health << endl;

    }

    int main()
    {
        //STRUCT
        MonsterStruc monster1 = {"Durotan", 140};
        MonsterStruc monster2 = {"Frinu", 200};
        //ENUM
        MonstersEnum monsterE1(MONSTER_OGRE);
        MonstersEnum monsterE2(MONSTER_SLIME);
        //FUNCTIONS
        printMonster(monster1, monsterE1);
        printMonster(monster2, monsterE2);

           return 0;
    }

    Hey Alex I would like to know if theres any advice you can give me about my code. It runs and does the job but i dont know if i could improve it. (Nice tutorials btw) Thanks!.

    • Alex

      A variable of type MonsterEnum should be inside MonsterStruc rather than declared in main(). Then printMonster() only needs one parameter.

      Also, don't use "using namespace std;"

  • Gerald

    Maybe your question should say that you want a string function? Did it exactly like your answer except I didn't do the std::string function. No biggy, just a thought.

    Otherwise keep up the good work. Your website is awesome!

  • kris

    I think their should be more clarity you cause names to run into eachother alot although sometimes lowercase it confuses the reader. but i understand each block the previous variable doesn't matter but you know

  • Damien

    Hi Alex,

    When trying the quiz i ended up trying to do it a different way to your solution. But had problems.

    I got an error (line 23): "no operator "<<" matches these operands".
    and a linker error: "binary '<<' no operator found which takes a right-hand operand of type 'MonsterType' (or there is no acceptable conversion)"

    I understand your solution fine. But am just wondering why this error pops up in mine. Is it something to do with the type for monster not being a string???

    Thanks!

    • Alex

      enum classes are considered a unique type, and std::cout doesn't know how to output these. You'll need to write a function to convert a MonsterType to a const char* or std::string (preferred).

  • Abhi

    Any more programs to practice on?
    I failed quiz 1 so I want to do another to ensure I am trained.

    Maybe you can add more quizes in each chapters comprehensive quizzes section

  • KIRPAL

    Can you help me to understand this line,

        MonsterType type;

    why did you put MonsterType before a variable "type"?

    i'm a beginner

    • Alex

      'type' is the name of the variable being declared, and MonsterType is the type of the variable being declared. This is similar to how we declare variable x as being an integer via "int x;". In this case though, instead of an integer, we're using an enumerated type (MonsterType) of our own creation.

  • subh

    I wrote the code of question-1 in another way without using getMonsterTypeString(monster) function as below, which produces intended result.
    Does my code have any limitations?
    #include <iostream>
    #include <string>

    // Define our different monster types as an enum
    using std::cout;
    using std::endl;
    enum class MonsterType
    {
        OGRE,
        DRAGON,
        ORC,
        SPIDER,
        SLIME
    };

    struct Monster
    {
        MonsterType type;
        std::string name;
        int health;
    };

    Monster printMonster(Monster monster)
    {
       cout << "This Monster name is: " << monster.name ;
       cout << " and has " << monster.health << " health\n";
       return monster;
    }
    int main()
    {
        Monster ogre = { MonsterType::OGRE, "Torg", 145 };
        Monster slime = { MonsterType::SLIME, "Blurp", 23 };

        printMonster(ogre);
        printMonster(slime);

        return 0;
    }

    • Alex

      Seems fine, though I don't know why function printMonster() is returning anything. It would be better if the function returned void and didn't have a return statement.

  • Fern

    • Alex

      There are a couple of approaches you could use. If the number of creature types is limited (e.g. 64 or less), you could turn CreateType into a fixed-width integer and set up the CreateType enum as a set of bit flags. Then you could do something like:

      Another way to do this would be to declare creatureType as an array of CreatureType instead of a single CreatureType. Then you could do:

      We cover arrays in chapter 6. But for this use, bit flags seems like the better choice.

  • Nyap

    • Nyap

      why can I use fixed-width integers without the cstdint header? is cstdint #included in iostream?

      • Nyap

        hmm it seems like it is
        also, I did the quiz wrong, because it always says "ogre" regardless of the monsters type
        I fixed it (if anybody cares lol): http://pastebin.com/qtXivgyq

      • Alex

        No idea, it's possibly included from some other file you've included, or your compiler is including it by default.

        But don't rely on that -- you should always explicitly include whatever headers you need.

  • J3ANP3T3R

    it happened again. im having errors with the instantiation.

    // RPG.h
    #ifndef RPG_H
    #define RPG_H

        enum class monType
        {
            MT_OGRE,
            MT_DRAGON,
            MT_ORC,
            MT_GIANTSPIDER,
            MT_SLIME
        };

        struct MonsterInfo
        {
            std::string name = "UNKNOWN";
            int health = 100;
            monType type = monType::MT_OGRE;
        };

    #endif

    // RPG.cpp
    #include "stdafx.h"
    #include <iostream>
    #include "RPG.h"

    void printMonster(MonsterInfo monsterToPrint)
    {

    }

    int main()
    {

        MonsterInfo monOgre1 { "OGRE 1",100,monType::MT_OGRE };
        return 0;
    }

    the line MonsterInfo monOgre1 { "OGRE 1",100,monType::MT_OGRE }; is giving me this error message
    1>d:visual studio community 2015peters projectsrpgrpgrpg.cpp(16): error C2440: 'initializing': cannot convert from 'initializer list' to 'MonsterInfo'

    EDIT : oh never mind it seems that removing the default values for the struct removes this error. but how can i add default values for members of the struct that was not initialized ?

    • Alex

      Visual Studio 2015 won't let you use both non-static member initialization and initializer lists with a struct. I hope they fix that in the next major version.

      In the meantime, you'll either have to choose one or the other (I'd recommend the initializer lists), or upgrade to full classes.

  • J3ANP3T3R

    Just a quick question when should you always use ";" ? on all of our single line statements we used ; to terminate a line of code but i noticed on some of our functions like main() and any other function we create in the main.cpp file we dont use ; but on some of our function we use ; and whether i use ; or not on main(){}; the compiler wont make any error messages. what should be the standard practice ?

    • Alex

      You should use ; whenever you're terminating a statement, whether it's one line or many.

      > but on some of our function we use ;

      We only use ; for forward declarations. Function definitions don't need a ; after the closing block -- I'm not sure why.

  • Radion

    Unfortunately, the code for C++11 version doesn't work. But when I remove class from enum and perform all related changes, everything works perfectly.

  • Indorfin

    I just want to say thank you so much for these tutorials! This is one of the few sites I disable ad-block on.

    I also wanted to say that I like what you chose for a quiz. The problem is, I made something similar as soon as enumerated classes were explained!

    Once I learn how to make it keep repeating turns until someone dies, I'll be able to make it possible for someone to "win"! Less than a week ago I didn't know ANY coding, so even this little faux-game is pretty amazing to me! Thank you for showing me how easy it is to get started.

    • Alex

      You're welcome! Loops (which will allow you to make repeating turns) are explained in the very next chapter. You're almost there!

    • I have improved the code a little...

  • Chris

    I know I wrong at the member Monster(I didn't insert the monster type). But I am so curious why the result of my code like this(codeblocks) :
    ___________________________________________________________
    This 1 is named Torg and has 145 health.
    This 1 is named Blurp and has 23 health.

    Process returned 0 (0x0)   execution time : 0.009 s
    Press any key to continue.
    ___________________________________________________________

    1?? here's the code. I have checked them all and didn't found the mistake.

    Thank you.

    • Alex

      This function is wrong:

      Your second line calls function type() but discards the result, and inside your cout statement, you're printing the address of function type() rather than making a call to it.

      This should work:

  • Rob G.

    This is about the string. A more efficient program would be to use structs alone, and use strings instead of enum members. On the other hand Alex maybe you wanted us to struggle with the enums...
    Am really getting a lot out of the course. Thx for ll the hard work u put into this!!

    Load up your objects and manipulate them

  • R00kie

    Hi Alex,

    I was trying to do this program with two structs instead of one struct and one enumeration. Is that possible ? I didn't quite figure it out to make it work with 2 structs and not use the enumeration.

    One more thing ..where can I find more quizes about structs ? it seems like an important chapter and I wanna do more exercises with structs..where can I find some ?

    It would be great if you could give us more exercises at the end of chapter 4.

    • Alex

      Possible? I suppose. Sensical? Unsure. You'd have to tell me more about how you were trying to solve the problem with 2 structs.

      For now, I'd advise looking on Google for more information on structs. Structs are super-important because their cousin, the class, is a relative of the struct. However, we'll cover classes in extensive detail later, so if you understood the struct lesson reasonably well, you shouldn't have anything to worry about.

  • Janee

    Hi there,

    How do you check the compiler version? I am using Microsoft visual studio 2013. Anyway to find out? thanks in advance

  • Cameron

    Can i ask you something?
    When you start this program do you start with main?
    I get kind of lost when i just start ilon my own
    Hopefully it will come with time

    • Alex

      Yes, programs always start at the top of function main().

    • Keith

      I may be wrong, but the way I read Cameron's question was 'how do you approach writing a solution for this?'.

      Yes, this will definitely come with time and experience. The way I approached this was to look at what data we needed to store and manipulate, and start with this - I defined the Monster struct first, and included a variable of MonsterType which I knew would be an enum. Then I wrote the enum.

      Once I knew what my struct looked like the next thing I did was to write the function to print it out. Then finally I wrote main() to create some Monster variables and send them to the print function.

      No real right or wrong way, but sometimes it can help to focus on how you are going to store the data (a struct in this case), get that right then work on the functions to do something with that. Main() is really the glue that holds all the pieces together, and often isn't doing much more than creating variable instances and firing them off to functions - that's why I did that bit last once I was certain how the structures and the function were going to operate.

      • Alex

        Aah, you could be right. My method for tackling this would be similar to yours. I'd start with the data (enums, structs, classes, etc...). I'd probably sketch out main() next. Then I'd progressively write the functions that were called in main().

  • Minh

    There is a mistake in non-C++11 solution.
    At line 43, in GetMonsterTypeString, the letter "G" must not be capitalized. It must be getMonsterTypeString.

  • Todd

    Typos.

    "A block of statements (aka. a compound statement) that is treated by the compiler as if it were a single statement." (remove 'that')

    "Typedefs allow us to alias (give an alias for) a type’s name." (alias is a noun, not a verb)

    "And finally, structs offer us a way to group related variables into a single structure, (remove comma) and access them..."

    For the following, I believe the function names should start with a lowercase letter:

    "Write a function named PrintMonster()..."

  • zhiwei

    This is my solution. Seems your's is better. I need to review my code.

  • Eric

    My code is nearly identical, but I opted to put both the Enumeration and Struct inside header files.  I think it is worth mentioning that the order in which you #include the header files in EXTREMELY important.

    Compiles fine

    does not compile and gives plenty of errors that are very misleading.  It took a me few minutes to figure out why it wasn't working.  Thought it was worth posting in case someone else does the same thing I did.

    • Alex

      If the order of includes makes a difference, then you did something incorrectly in one of your header files. :)

      In this case, you have something in Structs.h that uses something in Enums.h. Therefore, Structs.h should #include Enums.h itself.

      Once you do that, it won't matter which order you #include them in your main program.

  • Gerrod

    The non-C++11 solution is wrong. The code won't compile because MonsterType isn't a class or namespace. You need to get rid of class in enum class and delete all the MonsterType:: and just put the monster type.
    This compiles on CodeBlocks 13.12

Leave a Comment

Put all code inside code tags: [code]your code here[/code]