Search code examples
c++oopinner-classesencapsulation

How to encapsulate a class that is only being used inside another class?


Shown below is a rough structure of the program.

class Room 
{
private:
    Node* content;
public:
    void someRoomMethod();
};

void Room::someRoomMethod() {}


class Node
{
private:
    Node* nextNode;
    std::variant<int, float> data;
public:
    void someNodeMethod();
};

void Node::someNodeMethod() {}

As I mentioned in the title Node is not being used anywhere other than inside Room. I've tried to encapsulate Node by making it a nested class but it didn't work.

// Room.hh

class Room 
{
private:
    Room::Node* content; // ERROR: no type named "Node" in "Room" -- GCC

public:
    void roomMethod();

    class Node()
    {
    private:
        Node* nextNode;
        std::variant<int, float> data;
    public:
        void someNodeMethod();
    }
};

// Room.cpp
void Room::someRoomMethod() {} // sees Room in Room.hh

// Node.cpp
void Room::Node::someNodeMethod() {} // sees Node in Room.hh

Questions:

  1. How exactly should I encapsulate Node so that I could create a variable of type Node inside Room and so that Node couldn't be used anywhere except inside Room. Please note that I will need a linked list of type Node inside each instance Room.

  2. Should methods of Node be moved to external .cpp file like it is now? Is it a good practice?


Solution

  • Declarations of a nested class are parsed lexically (the same as at file scope). Simply move the usage of Node after the definition:

    class Room 
    {  
      private:
    
        class Node
        {
          // ...
        };
      
        Room::Node* content; // fine, Node is defined already
    
      public:
         // ...
    };
    

    Since Node is only used inside Room it should be private.


    Yes, you should move the definitions of Node methods to a .cpp file to separate implementation and interface. This is the same as for regular class methods.