1

想象一下从一个基类派生的多个类。所有班级都需要相互了解,这不是一个选择,因为这是我正在从事的一个更大的项目。由于它的简单性,我将使用虚构的inventory - item关系作为示例。

class Inventory : public Base {
    std::vector<Base*> m_items; // These CAN be Items
};

class Item : public Base {
    Base* m_parent; // This CAN be Inventory
};

这两个类显然位于不同的文件中,它们需要使用彼此的方法,而它们的基类没有这些方法。注意单词 CAN,而不是 MUST,这意味着 m_parent 和 m_items 可以是从 Base 派生的任何类的对象。所以 Item 的父级可能是Inventoryor TreasureChest

tl; dr 两个类必须能够相互通信,而无需知道彼此的类型。如何以及什么是实施此类活动的最佳方式?

4

3 回答 3

1

一种方法是为基类中的通信类型定义一个抽象函数。然后在你的派生类中实现这个函数。这使您可以处理所需的每种类型的通信。

但是通过两种方式引用,您必须更加谨慎地删除此类对象。这种类型的架构非常容易出错。

对于通信的两种方式引用可能如下所示:base.h:

class Base {
  void doCommunication(Base *caller) = 0;
};

库存.h:

class Inventory;      // forward declaration for Item class
#include "Item.h"

class Inventory : public Base {
   void doCommunication(Base *commCaller) { 
      // check type
      Inventory *invCaller = dynamic_class<Inventory*> (commCaller);
      if(invCaller != nullptr) {
         // called from inventory and you are able to use inventory

         return;  // you can stop here cause commCaller can only be Base class instead but not Item
      }

      Item *itemCaller = dynamic_class<Inventory*> (commCaller);
      if(invCaller != nullptr) {
         // called from item and you are able to use item

         return;  // you can stop here cause commCaller can only be Base class instead but not inventory
      }
   }
};

Item.h 看起来与库存类非常相似,doCommunications 必须为项目特定功能覆盖。

我还不能测试代码,但它应该可以工作。dynamic_cast 的原因,您可以转换为您需要的目标对象并调用所需的函数。如果失败,你会得到一个 nullptr。

希望能帮助到你。

欢呼卢卡斯

于 2012-11-26T22:45:21.500 回答
1

在您的示例中,没有任何实际问题:两个类之间没有直接依赖关系,并且您没有显示实现的任何部分。如果实现实际上需要从相应的其他类访问特定InventoryItem方法,则可以将每组操作分解到相应的基类中,也可能派生自Base并提供合适的函数。

例如

// base.h
class Base {
public:
    virtual ~Base();
};

// abstractitem.h
class AbstractItem: public Base {
public:
    virtual int weight() const = 0;
};

// abstractinventory.h
class AbstractInventory: public Base {
public:
    virtual int totalWeight() const = 0;
};

// item.h
class Item: public AbstractItem {
public:
    int weight() const;
    // uses of AbstractInventory
};

// inventory.h
class Inventory: public AbstractInventory {
    void addItem(AbstractItem const* item);
    int totalWeight() const;
    // uses of AbstractItem
};

请注意,库存和项目的抽象和独立操作只是被分解出来。尽管具体对象实际上能够相互调用,但接口或实现之间没有任何依赖关系。

于 2012-11-26T23:56:42.647 回答
0

两个班级可以“互相认识”就好了。只需在其用户的头文件中转发声明引用的类,并且仅在cpp(而不是h)中包含引用的类头...

啊:

struct B; // fwd decl

struct A
{
    B* b;

    void fa();
};

A.cpp:

#include "A.h"
#include "B.h"

void A::fa() { b->fb(); }

乙:

struct A; // fwd decl

struct B
{
    A* a;

    void fb();
};

B.cpp

#include "B.h"
#include "A.h"

void B::fb() { a->fa(); }

这显然是一个无限的运行时循环,但你明白了。

于 2012-11-27T00:11:28.430 回答