8.x — Chapter 8 summary and quiz

Quick review

std::string offers an easy and safe way to deal with text strings. String literals are always placed between double quotes.

Enumerated types let us define our own type where all of the possible values are enumerated. These are great for categorizing things.

Enum classes work like enums but offer more type safety and don’t pollute the encapsulating namespace quite as much.

And finally, structs offer us a way to group related variables into a single structure and access them using the member selection operator (.). Object-oriented programming builds heavily on top of these, so if you learn one thing from this chapter, make sure it’s this one.

Quiz time


Question #1

In designing a game, we decide we want to have monsters, because everyone likes fighting monsters. Declare a struct that represents your monster. The monster should have a type that can be one of the following: an ogre, a dragon, an orc, a giant spider, or a slime. Use an enum class for this.

Each individual monster should also have a name (use a std::string), as well as an amount of health that represents how much damage they can take before they die. Write a function named printMonster() that prints out all of the struct’s members. Instantiate an ogre and a slime, initialize them using an initializer list, and pass them to printMonster().

Your program should produce the following output:

This Ogre is named Torg and has 145 health.
This Slime is named Blurp and has 23 health.

Show Solution

9.1 -- Arrays (Part I)
8.6 -- Random number generation

61 comments to 8.x — Chapter 8 summary and quiz

  • Waldo Lemmer

    Wow, our solutions are almost identical! What do you think?

    (I like your taste in formatting at printMonster()'s definition xD)

    `using enum` was added to C++20! I can't use it for some reason, though. I get "expected an identifier" after `using` :(. It was added in 16.4, and I have 16.8.4 ( (Ctrl+F P1099R5)

  • kio

    It seems that we have same approach to it

  • Updated inspired by Aditya.

  • Ah, I had to look at the solution for this one. At first I thought enums were unnecessary because structs could handle everything, but now I see enums are lists of types of information within specific categories. I see how you can add an enum class as a member of a struct. I also see how to pass a struct to a function as a function parameter. I optimized your code by making series of "if" statements a "switch".

    • nascardriver

      Good improvement idea, I've added it to the lesson :)

      Remember that you always have to return from functions that have a return-type. If the value of `race` isn't handled in your `switch`-statement, your function causes undefined behavior.
      Variables of enum type can have values that are not represented by any enumerator.

      • Understood! I was getting a compiling error so I added

        outside of the switch. But you mean I should simply added a "default" statement at the bottom of the switch that returns an error message, correct?  I just added that and it seems to be compiling fine now :)

        • nascardriver

          There's no difference in behavior between returning in the `default` case vs returning after the `switch`-statement.

          It's better to return after the `switch`-statement, because your compiler will warn you if you forget to handle an enumerator. If you have a `default` case, the compiler won't warn.

          Try commenting out one of the cases to see for yourself.

  • yeokaiwei

    Some feedback. The printMonster function is inconsistent and confusing. Parameters like or are simple and easy to read. Just extensions of the initialization.

    Secondly, the monster type string has to be created with "getMonsterTypeString". If we just remove the monster type from the print function, it works.

    Lastly, creating a function to create a string for the monster type was not mentioned in the quiz.

  • This is my take on quiz i m not sure if it's very good it took my some time but the time i spent on it was worth! :D

    • nascardriver

      - Use an auto-formatter to format your code consistently.
      - Name variable descriptively. "m", "x" don't mean anything.
      - "0==Ogre, 1==Dragon, [...]" Those numbers are magic. If you change the values or add new types to the enum, this string is wrong. You can use your enumerators to create the message

      Otherwise very good :)

  • Aditya

    I modified the code to take the struct from the user as input since I was having a bit of trouble with that in the previous exercise. I'm not sure I've followed all the best practises... Any suggestions? apart from not using the namespace. I'm very lazy :p
    Really love these tutorials guys thank you so much!!

  • Jacob

    Hi there.

    For better or worse, I did not write a separate function for the monster type; I did it in the printMonster function:

    It seems to me that the species name ("Spider", "Ogre" etc) should have been included in the structure as well. Alternatively, I was tempted to initialize an array of structures to associate the enum with the species (I am an experienced C and Perl develorpr with lousy spelling :-) like this:

    In Monsters.h:

    In Monsters.cpp, the definition:

    and use a loop to search for the monster code.  But I decided to defer that kind of code to when *you* cover flow control and arrays.  I HATE if/else sequences so I used the switch statements, however premature.  This is one HUGE gap in Perl.

    • nascardriver

      If you include the species name in the struct, you not only have redundant information (The enum and string) which could diverge, leading to unpleasant results, but you're also wasting a lot of memory, because you're storing the same string in many instances of the struct.

      If the enum is contiguous (Doesn't have gaps between enumerators), you can use an array of names and index it with the enum for constant access time

      If the enum isn't contiguous (Or you suspect it might not be contiguous in the future), you can use a switch-statement or `std::map`. `std::map` isn't covered on learncpp. It maps values of one type to values of another

      Like a switch-statement, `std::map` has logarithmic access time.

      With your `MonsterType` suggestion, you'd have to loop over all elements in the array if you want to know the name of the last monster.

      • Jacob

        > ... you not only have redundant information ...
        I agree it would have been redundant.  Worse, a typo could mess it up something fierce!

        I just looked up std::map in

        OUCH! :-)

        I'll have to file that away until I have the chance to study some examples. The examples at are kinda obtuse IMO.  (I do not discount the possibility that the obtuse one could be me. :-)

        Thank you for bringing this feature to my (our?) attention.  But there's gotta be a simpler way to simply set up and access such a data structure without getting into the subtleties of containers and iterators.

        • nascardriver

          The most basic way of doing this is via a `switch`-statement, but that gets long. The next easiest step is `std::map`. The standard library plays a huge rule in C++ and you won't get far without it.

  • Ismael

    I feel this chapter was a bit rushed. I struggled my first attempt doing the quiz, mostly on remembering to use '::' or '.' for the structs/enum class. I feel like part of the chapter should cover how to take user input for structs.

    Also, is it necessary to '#include <string>' for compatibility reasons?

    This is what I got:

    This Orge is named Torg and has 145 health.
    This Slime is named Blurp and has 23 health.

    Please enter the following information for "Dragon".
    Please enter the Dragon's name: Bork93
    Please enter the Dragon's health: 9000

    This Dragon is named Bork93 and has 9000 health.

    I want to add that, it seems that editing a comment here seems to break the "code" tag.

    • nascardriver

      User input into structs was part of S.4.7's quiz. You can always go back to earlier lessons if you don't remember something.

      Code tags work after refreshing the page.

      Yes, you need to #include <string>. Otherwise your code won't work with different compilers. Always include everything you use.

      `getinfoMonster` should only take the `typemonster` as a parameter, then create the `infomonster` as a local variable. When you do that, line 75,76 should be

  • Tony

    At first my solution was similar but my Monster struct had only two members (name & health). Thus, my program was much more complex. After looking at the solution I realized that having a MonsterType type member in the struct was actually the best.

    By the way, to find out the actual "solution" myself I had to check chapter "Enumerated types" again (the example where it uses std::string as a return value of the function). Is that normal at all? Couldn't get the std::string part on my own apparently!

  • AE35_Unit

    I had to look at the solution several times. Unfortunately I struggled with this. I'm sure it's the fact we have a an enum inbedded in a struct. I would have liked to have seen more guidance on such things in the lessons.  Thanks for chapter though.  I'm pressing on to chapter L.5.x as it looks like quite a lot that I'm comfy with. See ya there, cheers.

    Written with Geany on a raspberry pi 4

  • sami

    Is the following OK, if I want to initialize all the struct members?

    • nascardriver

      Unless you use the initial values, use empty curly braces. For `name`, use empty curly braces in either case. Passing it an empty string literal is slower.

  • Yung

    Would you please elaborate on this statement after 'where all of ...' ?

    >>Enumerated types let us define our own type where all of the possible values are enumerated.

  • CvB

    Hi Alex and nascardriver,

    I've noticed that a lot of comments/questions pertaining to this quiz are listed under the comments for summary and quiz of chapter 6. I assume they got misplaced while reordering the lessons. Maybe you can look into it and transfer the appropriate comments to this lesson.

    Cheers and keep up the good work!!

  • Cerezas

    Changing exercise function prototype:


    would improve reusability.

  • Hiep

    In the quiz solution, enum class MonsterType was declared before std::string name in Monster struct declaration. However when I try to print out the size of enum class and std::string

    This is what I get

    Will this affect data structure alignment?

    Declaring enum class first before std::string

    This will print

    Declaring std::string first before enum class

    This will print

    • nascardriver

      Good call. Alignment isn't something we care about in the tutorials, and also in practice it is mostly ignored unless memory usage is of concern. Having a logical structure of members by what they're used for is often more helpful than saving a couple of bytes.

  • Ef

    EDIT: Nvm I worked out that the issue only occurs with the ENUM Type

    For some reason my code doesn't let me print the attributes unless I use static casts:

    #include <iostream>
    #include <string>
    #include "monsters.h"

    int main()
        monsters::MonsterStats new_monster{DetermineType()};

        std::cout << "Oh no it is a " << new_monster.Name << '\n';
        std::cout << "It is a  " << static_cast<int>(new_monster.Type) << " type.\n";
        std::cout << "It has  " << new_monster.Health << " health.\n";
        std::cout << "And it does  " << new_monster.Damage << " damage.\n";

        return 0;

    #include <iostream>
    #include <cstdlib>
    #include "monsters.h"
    #include <time.h>

    monsters::MonsterStats DetermineType()
        int monster{rand() % 5};

            case 0:
                return Ogre;

            case 1:
                return Dragon;

            case 2:
                return Orc;

            case 3:
                return Giant_Spider;

            case 4:
                return Green_Slime;



    enum class MonsterType

    namespace monsters
        struct MonsterStats
            std::string Name;
            MonsterType Type;
            double Health;
            int Damage;

    monsters::MonsterStats DetermineType();

    inline monsters::MonsterStats Ogre{"Ogre", MonsterType::Ogroid, 120, 10};
    inline monsters::MonsterStats Dragon{"Dragon", MonsterType::Reptillian, 120, 10};
    inline monsters::MonsterStats Orc{"Orc", MonsterType::Ogroid, 120, 10};
    inline monsters::MonsterStats Giant_Spider{"Giant Spider", MonsterType::Arthropod, 120, 10};
    inline monsters::MonsterStats Green_Slime{"Green Slimes", MonsterType::SLIME, 120, 10};


  • Gabe


    • nascardriver

      `getMonsterTypeString` calls for a `switch`-statements. The compiler can optimize `switch`-statements better than `if`-statements. When you have a limited set a values (eg. enum or char) that you want to check for equality, use a `switch`-statement.

  • Dudz

  • Al

    You said that both `enum` and `struct` declarations could be included in a header file without loss of performance because their declaration doesn't allocate memory. Is this also true for:

    1. enums where we give explicit values to each enumerator,
    2. enum classes with or without explicit values given, and
    3. structs with default values?

    Thank you in advance.

  • Raton

    "Enum classes [...] don’t pollute the standard namespace quite as much."

    Don't you mean the global namespace? (third paragraph)

    • nascardriver

      "standard" is wrong, "global" is better, but an enum can be defined in a namespace that is neither `std` nor global. I changed it to "encapsulating namespace". Thanks for pointing out the mistake!

  • giang

    Hi, I tried to write a program to solve the quiz above but my program works well when I just use 'enum' instead of 'enum class'. When I tried 'enum class'and '::' operator, the compile threw me errors that said:'MonsterType is not a class or namespace'. Can someone explain this situation to me, please? Thanksss

  • Lars

    Here is my attempt on a solution.




  • Suyash

    Here is my solution to the quiz question... I have decided to split the code into 3 files: main.cpp, monsters.h and monsters.cpp files... The primary reason why I decided to modularize my code was to gain some extra practice by using header files to encapsulate different logical sections of a project.

    The code works as expected, without any kind of compilation/linking problems... I would love to hear your opinions about it and you are more than welcome to bring into my observation anything that missed my eyes...

    1. monsters.h

    2. monsters.cpp

    3. main.cpp

    • nascardriver

      Looks great, keep it up!

    • Lars

      A bit more elegant than my attempt. I like it :)
      One question:
      In monsters.cpp line 22 is it best practice to specify namespace when calling getTypeString? More specifically, is it best practice to use
      (a) monsters::getTypeString, or
      (b) getTypeString

      • nascardriver

        You're already in the namespace, there's no need to specify the namespace. Just like you don't use `::` whenever you access the global namespace and you don't say "on earth, on this continent, in this country, ..." every time someone asks you where something is.

  • fxr

    This is my attempt a the quiz I opted to have user input for monster creation any suggestions on how to improve it?

    • nascardriver

      - Inconsistent formatting. Use your editor's auto-formatting feature.
      - Initialize variables with brace initialization for better type safety.
      - Use single quotation marks for characters ("\n" vs '\n')
      - Line 21+: Magic numbers in strings, use your enum.
      - Your function names aren't great. "listMonsters", "getMonsterName", "getMonsterHealth", "getMonsterType", "getMonsterTypeName" or similar are a lot more useful.

      • fxr

        thank you very much for the response will keep all of that in mind

      • fxr

        Hello, it's me again nascardriver I was looking at my code improving the things you mentioned I have a question how could I use my Enum instead of magic numbers for the selection of a monster type.
        Heres the part I'm talking about.

        • nascardriver

          I thought you'd ask that, but I answered the same question the day before and couldn't find my reply, so I hoped you'd figure it out. You can cast your enumerators to `int` to make them printable, then just replace your magic strings with the `int`s.

          Now, when you move around your enumerators, the list is correct.

    • hi

      I may have broken your program.


      What is your monsters name?
      What is your monsters health?
      Which of these types is your monster?
      0. Ogre
      1. Dragon
      2. Orc
      3. Giant spider
      4. Slime
      answer with the number in front of the type
      This I don't understand. is named Destoyer it has 2147483647 health.

      • hi

        The number 2,147,483,647 is the maximum positive value for a 32-bit signed binary integer. It is therefore the maximum value for variables declared as int, and the maximum possible health..

        When he says "answer with the number in front of the type", he means you should type "0" for Ogre, "1" for Dragon, etc.

  • kavin

    I made one like this since its asked in the question to print out struct members. Its kind of big but, is there any way to make this simple ?

    • nascardriver

      The `struct` should describe the data that it holds, but not the values (eg. names of the monsters).

      then pass only a `Monster` to `printMonster`, no other parameters.

      Try rewriting your code that way. You seem to have misunderstood the purpose of structs and enums.

      • kavin

        I am going nuts with this from morning and still can't figure out how to pass all values at once using just 1 argument like you said and print all the results in 1 function ! I understood the use of struct part you said but not the other thing .

        Sorry for being a super noob and firing series of questions at you. I don't want to move to next chapter without understanding this correctly !

        • nascardriver

          > Is this correct ?
          If you want to create multiple monsters, you need an array. You're declaring `monsters` as a single `Monster`, but trying to initialize it with multiple `Monster`s. That doesn't work.

          Inside of `printMonster`, you can access the monster the same way.

  • hausevult

    Woah, there are so few comments here! Well I like the way you use structs, really illuminating.

  • Kyle

    There is no link to the next lesson here.

Leave a Comment

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