想象一下,有一个派生自一个基类的多个类。所有类都需要相互了解,这不是一个选项,因为它是我正在工作的一个更大的项目。我将使用简化的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的父级可以是Inventory
或TreasureChest
。
tl; dr两个班级必须能够彼此沟通,而不必了解彼此的类型。 如何以及什么是实施此类活动的最佳方式?
答案 0 :(得分:1)
一种方法是为Base类中的通信类型定义抽象函数。 然后在派生类中实现此函数。 这使您可以处理所需的每种类型的通信类型。
但是对于双向引用,您必须更加谨慎地删除此类对象。 这种类型的体系结构非常容易出错。
对于通信的双向引用可能如下所示: base.h:
class Base {
void doCommunication(Base *caller) = 0;
};
Inventory.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。
希望它有所帮助。
欢呼声 卢卡斯
答案 1 :(得分:1)
在您的示例中,没有任何实际问题:两个类之间没有直接依赖关系,并且您没有显示实现的任何部分。如果实现实际上需要从相应的其他类访问特定的Inventory
和Item
方法,那么可以采用的方法是将每组操作分解为相应的基类,也可能派生自{{ 1}}并提供合适的功能。
例如
Base
请注意,库存和项目的抽象和独立操作只是考虑因素。接口或实现之间没有任何依赖关系,尽管具体对象实际上可以相互调用。
答案 2 :(得分:0)
两个班级可以“彼此了解”就好了。只是在其用户的头文件中转发声明引用的类,并且只在cpp中包含引用的类头(而不是h)......
<强> A.H:强>
struct B; // fwd decl
struct A
{
B* b;
void fa();
};
<强> A.cpp:强>
#include "A.h"
#include "B.h"
void A::fa() { b->fb(); }
<强> B.h:强>
struct A; // fwd decl
struct B
{
A* a;
void fb();
};
<强> B.cpp 强>:
#include "B.h"
#include "A.h"
void B::fb() { a->fa(); }
这显然是一个无限的运行时循环,但你明白了。