c ++如何创建相互依赖的类

时间:2013-05-21 06:06:17

标签: c++ class

我有一个存储类。这类成员经常被修改。 每次修改成员时,我都想保存类的状态(克隆类实例并保存它)。 所以我想创建一个新类,它将保存这些状态。

例如:

假设我在文件storage.h中有一个Storage类

class Storage 
{
 public:
   Int m_cnt;
   <lots of other members...>

   StorageHistory m_his;
};

和文件storagehistory.h中的StorageHistory类

class StorageHistory 
{
 public:
   std::vector<Storage> m_history_vec;
};

假设:

  1. StorageHistory类应该保存在Storage类中。原因是Storage类是可以在所有类/包中访问的主类。为了最大限度地减少代码中的更改,我希望S torageHistoryStorage类相结合。
  2. 由于创建了StorageHistory的多个实例,因此
  3. Storage不能是静态或单例。
  4. 问题:

    1. 无法编译此代码。 storage.h需要在storagehistory.h之前编译,反之亦然
    2. 如果StorageHistory无法存储Storage,那么我该保留吗?谁是这个班的老板?
    3. 需要帮助来定义这两个类别之间的联系吗?

4 个答案:

答案 0 :(得分:1)

添加到您的标题文件

storage.h定义

class Storage;  //to declear the class before the include

#include "StorageHistory.h"

//continue with the old declearation 

class Storage{
   ....
}

StorageHistory.h

class StorageHistory;  //to declear the class before the include

#include "Storage.h"

//continue with the old declearation 

class StorageHistory{
   ....
}

记得首先在文件中包含防护。

这可以针对所有类进行,以避免将来出现此类问题。

答案 1 :(得分:1)

首先:除非您定义纯数据结构,否则不要将数据成员公开。然后:Int不是C ++类型。

现在回答您的问题:您可以使用前瞻性声明。由于StorageHistory直接用于Storage,因此无法向前声明,Storage仅用于std::vector中的模板数据成员(即StorageHistory)如果它仅被声明为变量,那么该模板不需要Storage的定义。只有在使用向量方法时才需要定义。

所以这是解开的代码:

StorageHistory.h

#include <vector>
class Storage;
class StorageHistory 
{
  std::vector<Storage> m_history_vec;
public:
  /* method declarations */
};

Storage.h

#include "StorageHistory.h"
class Storage 
{
  int m_cnt;
  /* <lots of other members...> */
  StorageHistory m_his;
public:
  /* method declarations */
};

Storage.cpp

#include "Storage.h"
#include "StorageHistory.h" //not necessarily needed, because implicitly included, but thats a matter of coding style

/* ... Storage methods definitions ... */
void Storage::changeVar(/*...*/)
{
  m_his.push_back(*this);
  /* ... */
}

StorageHistory.cpp

#include "StorageHistory.h"
#include "Storage.h"

/* ... StorageHistory method definitions ... */

答案 2 :(得分:0)

你实际上在做memento设计模式。您当前的编译问题将随着前向声明而消失。但是为了更好的设计和实施,您可以看到thisthis

答案 3 :(得分:0)

您需要使用前向声明才能使解决方案正常工作。最简单的方法是将这些类放在同一个头文件中(但可能会有所不同):

class StorageHistory; // *** Forward declaration ***

class Storage 
{
public:
    Int m_cnt;
    &lt;lots of other members...&gt;

    StorageHistory m_his; 
};

class StorageHistory 
{
public:
    std::vector<Storage> m_history_vec;
};
但是,我不喜欢你的解决方案。 m_his将包含一个Storage类列表,所有这些类都将包含一个Storage类列表(尽管是空的)。

我创建一个带有存储向量映射的单例,并使用包含UID的容器包装存储。

class StorageContainer
{
private:
    static int nextUID = 0;
    int uid;
    Storage data;

public:
    StorageContainer()
    {
        uid = nextUID++; // Watch out for concurrency problems
    }

    Storage & GetData()
    {
        return data;
    }
};

然后,您可以通过其UID访问存储历史记录。

class StorageHistory
{
    // The usual singleton stuff

    private:
        std::unordered_map<int, std::vector<Storage>> history;

    public:
        std::vector<Storage> & operator[] (int uid)
        {
            auto iter = history.find(uid);
            if (iter == unordered_map::end)
            {
                std::vector<Storage> newHistory;
                history[uid] = newHistory;
            }
            return history[uid];
        }
};