【问题标题】:How to encapsulate a class that is only being used inside another class?如何封装仅在另一个类中使用的类?
【发布时间】:2023-09-22 18:12:02
【问题描述】:

下图是程序的大致结构。

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() {}

正如我在标题中提到的那样,Node 除了在Room 内部之外,没有在任何地方使用。我尝试通过将 Node 设为嵌套类来封装它,但它不起作用。

// 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

问题:

  1. 我究竟应该如何封装Node,以便我可以在Room 中创建一个Node 类型的变量,这样Node 就不能在除Room 之外的任何地方使用。请注意,我需要在每个实例Room 内创建一个Node 类型的链接列表。

  2. 应该像现在这样将Node 的方法移到外部.cpp 文件中吗?这是一个好习惯吗?

【问题讨论】:

    标签: c++ oop inner-classes encapsulation


    【解决方案1】:

    嵌套类的声明是按词法分析的(与文件范围相同)。只需将Node的用法移到定义后即可:

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

    由于Node 仅在Room 内部使用,因此应为private


    是的,您应该将Node 方法的定义移动到.cpp 文件中以分离实现和接口。这与常规类方法相同。

    【讨论】:

      【解决方案2】:

      你必须至少声明一个类型才能使用它:

      class Room 
      {
      
      
      public:
          void roomMethod();
      
          class Node                          // no () 
          {
          private:
              Node* nextNode;
              std::variant<int, float> data;
          public:
              void someNodeMethod();
          };                                  // missing ;
      private: 
          Node* content;
      
      };
      

      【讨论】:

        最近更新 更多