gpt4 book ai didi

c++ - 所有派生类的通用接口(interface)

转载 作者:太空狗 更新时间:2023-10-29 21:20:38 25 4
gpt4 key购买 nike

我有基类 Item,它存储一些数据并授予访问者访问它的权限,例如:

class Item{
(...)
public:
int get_value();
double get_weight();
ItemMaterial get_material();
(...)
}

然后我有派生类,如 Weapon、Armor,它们添加了一些额外的数据:

class Weapon : public Item {
(...)
public:
int get_dmg();
(...)
}

我将这些项目存储在某个容器中:

std::vector<Item*> inventory;

接口(interface)的问题来了——如何访问派生类数据?我在想,得到了 3 个想法:

<强>1。独立接口(interface)

每个派生类添加其数据,如上所示,然后使用 dynamic_cast:

Item *item = new Weapon;
int dmg = dynamic_cast<Weapon*>(item)->get_dmg();

<强>2。通用接口(interface)类

创建一个包含所有访问器的接口(interface)类:

ItemInterface{
public:
virtual int get_value() = 0; //Item interface
virtual double get_weight() = 0;
(..)
virtual int get_dmg() = 0; //Weapon interface
(...)
}

然后是这样的:

Item : public ItemInterface{ (...) }

Weapon : public Item { (...) }

最后我们可以访问数据了:

Item *item = new Weapon;
int dmg = item->get_dmg();

<强>3。结合模板和枚举

这个想法可能有点奇怪 :-) 但是:

使用所有项目数据实现枚举:

enum class ItemData{
Value,
Weight,
Material, //Item data
(...)
Damage, //Weapon data
(...)
Defense, //armor data etc.
(...)
Null
}

在基类中有一些像这样的模板函数:

template<typename T>
T get_data(ItemData data){
switch(data){
case ItemData::Value: return _value; break;
case ItemData::Damage: return _dmg; break;
(...)
}
}

并访问如下数据:

Item *item = new Weapon;
ind dmg = item->get_data<int>(ItemData::Damage);

===

你认为应该怎么做?我将不胜感激任何建议!

问候。

最佳答案

您的第二个和第三个选项显然不是要走的路 - 每当您添加新类型的项目时,您还必须更改基类或枚举 - 这绝对不是什么如果您的代码需要任何基本形式的可维护性,您就会想要。

And here comes the problem with interface - how to get access to derived class data

首先您必须考虑“您的代码将在哪里执行此操作”?您的大部分代码处理整个 inventory应该只使用内容作为 Item* , 仅使用 Item 中的函数类(class)。

如果您有专门处理 Weapon 的代码对象,Weapon 所在的地方创建对象(并插入到 inventory 中),也可以将它们添加到另一个变量中,可能是

形式的武器列表
std::vector<Weapon*> weapons;

或者给一个成员变量Weapon*一类Warrior或类似的东西(但要注意,您现在将有两个指向相同对象的指针,因此您必须考虑所有权)。所以只处理武器的代码(例如 Warrior 的成员函数)不会访问 inventory得到 Weapon对象,它将始终使用 Weapon*直接地。

如果出于某些原因,您必须编写一些代码来对库存中的所有武器执行某些操作,然后编写一个函数来提取所有 Weapon使用 dynamic_cast 的对象(或者更好:让它成为一个迭代器函数),并在需要访问所有武器时重用这个函数。因此,您不会用动态转换弄乱您的代码,而是将它放在一个地方。

编辑:另一种选择(避免动态转换)是使用访问者模式,参见 this post .但我不太喜欢那个帖子的答案,在呈现的形式中,它将暗示循环依赖“Base -> Visitor -> Derived -> Base”,恕我直言,这是一个糟糕的设计。

关于c++ - 所有派生类的通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24104603/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com