12.17 — Nested types in classes

Consider the following short program:

There’s nothing wrong with this program. But because enum FruitType is meant to be used in conjunction with the Fruit class, it’s a little weird to have it exist independently from the class itself.

Nesting types

Much like functions and data can be members of a class, in C++, types can also be defined (nested) inside of a class. To do this, you simply define the type inside the class, under the appropriate access specifier.

Here’s the same program as above, with FruitType defined inside the class:

First, note that FruitType is now defined inside the class. Second, note that we’ve defined it under the public access specifier, so the type definition can be accessed from outside the class.

Classes essentially act as a namespace for any nested types, much as enum classes do. In the prior example, because we used an enum class, we had to qualify our enumerators with the FruitType:: scope qualifier. In this example, because FruitType is a normal enum that is part of the class, we access our enumerators using the Fruit:: scope qualifier.

Note that because enum classes also act like namespaces, if we’d nested FruitType inside Fruit as an enum class instead of an enum, we’d access the enumeration via a Fruit::FruitType:: scope qualifier. This double-scoping is unnecessary, so we’ve used a normal enum.

Other types can be nested too

Although enumerations are probably the most common type that is nested inside a class, C++ will let you define other types within a class, such as typedefs, type aliases, and even other classes!

Like any normal member of a class, nested classes have the same access to members of the enclosing class that the enclosing class does. However, the nested class does not have any special access to the “this” pointer of the enclosing class.

One other limitation of nested types -- they can’t be forward declared. However, this is rarely a problem in practice since the entire class definition (including the nested type) can generally be #included where needed.

Defining nested classes isn’t very common, but the C++ standard library does do so in some cases, such as with iterator classes.

12.18 -- Timing your code
12.16 -- Anonymous objects

33 comments to 12.17 — Nested types in classes

  • Waldo Lemmer

    The enumerators in this lesson don't follow the naming conventions in 9.2 (

  • Santos

    Hello sir,
    When I put &m_type instead of m_type, I get a garbage value. How, please explain

    • i am no expert and my answer is probably wrong but i think after the constructor is called the 'type' parameter is deleted so the reference is left with a garbage value

  • James

    Hey, the access functions could be const right?

  • The enum type 'Fruit::FruitType' is unscoped

    Q1: Despite the fact that enum type is enclosed in a class namespace, still we got the following warning, why is that?
    I think because FruitType is considered to be part of the class, it is not unscoped anymore.

    "The enum type 'Fruit::FruitType' is unscoped. Prefer 'enum class' over 'enum' (Enum.3)."

    >>However, the nested class does not have any special access to the “this” pointer of the enclosing class.
    is there any way to access or is it impossible in C++?

    >>One other limitation of nested types -- they can’t be forward declared.
    is this the same as when we forward declared a public member function and the define it outside of the class, is this what you were mentioning? This is the feature that doesn't work for nested types, right?

    • nascardriver

      Q1: `FruitType` will still happily convert to an `int`, which is undesirable most of the time.

      There's also still the potential for collisions with other enums defined in `Fruit`

      Q2: It's impossible, because nested types can be instantiated independently of the surrounding types.

      Q3: See my comment here
      That examples makes it impossible to use `C::E` in "b.hpp"

  • Thomas Kennings

    "Defining nested classes isn’t very common, but the C++ standard library does do so in some cases, such as with iterator classes. We’ll cover iterators in a future lesson."

    Iterators were covered in a previous lesson!

    • nascardriver

      This lesson is referring to lesson 16.3. Lesson 16.3 doesn't go into a lot more detail than P.6.17 did, but for now, there is no lesson about custom iterators.

  • Hello Alex!

    A trap I just stumbled into: Nested types cannot be forward declared. eg.

    I think it's worth mentioning.

  • Brandon

    If a class is divided into a header and .cpp file and you want to add an enum, which file should it go in?

    • Depends on the class and enum.
      If the enum is only used in the source file, you can declare it inside the source file.
      If the enum is used elsewhere, declare it in the header.
      If the enum is considered a part of the class, declare it inside the class.

  • Abhijit

    Can we put enum inside interface class?

  • Atas

    If my VS compiler is anything to go by then if we write

    then innerObject becomes a member variable of any Outer object, but if we do this

    then we're just declaring a class in the Outer:: namespace that has access to Outer's innards, correct? Would it make sense to do the first variation and is it done often?

    • Both versions create an inner class that has access to the outer class. The first version immediately instantiates `Inner`. It's the same as

      You'll find it a lot in C, especially with omitted type names, not so much in C++. Type and object declarations are easier to read when they're separate.

      • Atas

        Thanks! It's just that the idea of a class being a member of another class weirds me out, I gotta have an object of the said class be the member as well :-) Thankfully, from what I've googled, nested classes don't seem to be that popular of a feature in C++.

  • You should mention that you can forward declare enums. It could look like this:

    • Yiu Chung WONG

      I get a "Enumeration previously declared with fixed underlying type" error

      • The forward declaration of @FruitType has to have the same access specifier as it's definition (In this case, public), and line 10 has to specify the type.

  • Rohde Fischer

    A common quite useful example of using nested classes (at least in the Java world) is builders.  The basic idea is that some classes can get a lot of constructor arguments, and if you got a constructor signature looking like: Foo(string, string, string, string, string) it will be really hard knowing which string is which.  If I’m not much mistaken in C++ it would look roughly like this:

    This is a lot of work when creating the class, but it tends to pay off in the long run, and especially if one is creating an api this is a lot nicer to use, since now the user can just:

    Making this a lot more readable, it’s independent of order and it makes creating factories a lot easier.  Of course as in one of my other comments, it’s worth discussing the tradeoffs.  Because on any modern machine using this paradigm is of no consequence, unless one is doing something specifically intensive.  However, on things like embedded devices this might be a very bad design.  It is also an example utilizing the trick you present at: with returning the class itself for creating a fluent API.

    • Alex

      This is a great example. Thanks for sharing!

      • Rohde Fischer

        You're welcome, thanks for a great tutorial. Of course as everything else this is matter of taste :) I've also seen people make containers for every singly type in question, basically simulating a typedef, but in a typesafe and quite bloated way. Not sure I'm a fan, but I can see the idea, as long as one use an IDE that helps with the types.

    • Udit

      Hi sir,
      I dont understand, how this example is working

      According to my understanding there is only one way to call member function without creating an object, i.e. using 'static'. But how in this case we can explain that we are able to call 'get_info' without using object.

  • John Halfyard

    Hi Alex,

    I'm not the best on the ol' "Passing by Reference, Const" and all that jazz (will have to review 7.1-7.4 a few times I guess).  But in the code above:

    why do you not place 'const' after the () for each function?


    • Alex

      Because it wasn't needed for the example. But you're right, these should be flagged as const functions so they could be called with a const object.

  • James

    Good job Alex, but here am wondering how none static const private variable of the class Fruit "int m_percentageEaten = 0;" get to be initalized directly inside the class while you thought me in the previous lesson that only static const int and enum variable can be initialized inside the class that way. please Teacher tell me how this work.

    • Alex

      Initialization for static and non-static members works differently. Static members can only be initialized in the class if they are ints or enums. Non-static members can be initialized inside the class regardless of the type.

  • john

    Hi Alex! In the lesson on enumerators you mentioned we should prefer enum classes over enumerators if we have a C++11 compatible compiler since they are strongly typed and strongly scoped. What is the preferred way of using enumerations inside the class (using enum class complicates the access and we already limit the scope by having it inside the class)?

    • Alex

      Personally, I tend to use normal enumerations inside classes, since the double-namespacing from the class and the enum class seems overkill. But it's really up to you. Enum classes have some additional advantages (e.g. you don't have to worry about enumerator naming collisions if you have multiple nested enum classes).

Leave a Comment

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