Classes within Classes in C++: Nested Classes

You can provide a class definition inside another class definition. For example, you might decide that the SpreadsheetCell class is really part of the Spreadsheet class. And since it becomes part of the Spreadsheet class, you might as well rename it to Cell. You could define both of them like this:

export class Spreadsheet
{
public:
  class Cell
  {
  public:
    Cell() = default;
    Cell(double initialValue);
    // Remainder omitted for brevity
  };

  Spreadsheet(std::size_t width, std::size_t height,
    const SpreadsheetApplication& theApp;
  // Remainder of Spreadsheet declarations omitted forbrevity
};

Now, the Cell class is defined inside the Spreadsheet class, so anywhere you refer to a Cell outside of the Spreadsheet class, you must qualify the name with the Spreadsheet:: scope. This applies even to the member function definitions. For example, the double constructor of Cell now looks like this:

Spreadsheet::Cell::Cell(double initialValue)
: m_value { initialValue }
{
}

You must even use the syntax for return types (but not parameters) of member functions in the Spreadsheet class itself:

const Spreadsheet::Cell& Spreadsheet::getCellAt(size_t x, size_t y) const
{
  verifyCoordinate(x, y);
  return m_cells[x][y];
}

Fully defining the nested Cell class directly inside the Spreadsheet class makes the definition of the Spreadsheet class a bit bloated. You can alleviate this by only including a forward declaration for Cell in the Spreadsheet class and then defining the Cell class separately, as follows:

export class Spreadsheet
{
public:
  class Cell;

  Spreadsheet(std::size_t width, std::size_t height,
    const SpreadsheetApplication& theApp;
  // Remainder of Spreadsheet declarations omitted for brevity
};

class Spreadsheet::Cell
{
public:
  Cell() = default;
  Cell(double initialValue);
  // Omitted for brevity
};

Normal access control applies to nested class definitions. If you declare a private or protected nested class, you can only use it from inside the outer class. A nested class has access to all protected and private members of the outer class. The outer class on the other hand can only access public members of the nested class.