所有派生类的公共接口
Common interface for all derived classes
我有一个基类Item,它存储一些数据,并授予访问器对它的访问权限,如:
class Item{
(...)
public:
int get_value();
double get_weight();
ItemMaterial get_material();
(...)
}
然后我得到了派生类,如武器,装甲,增加了一些额外的数据:
class Weapon : public Item {
(...)
public:
int get_dmg();
(...)
}
我将这些item存储在某个容器中:
std::vector<Item*> inventory;
这里出现了接口的问题-如何访问派生类数据?我在想,有三个想法:
1。不同的接口
每个派生类添加自己的数据,如上所示,然后使用dynamic_cast:
Item *item = new Weapon;
int dmg = dynamic_cast<Weapon*>(item)->get_dmg();
2。通用接口类
创建一个包含所有访问器的接口类:
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:
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);
= = =
你认为应该怎么做?如有任何建议,我将不胜感激!
致意。
你的第二个和第三个选择显然是而不是——每当你添加一个新类型的项时,你还必须改变基类或枚举——如果你需要任何基本形式的可维护性,这绝对不是你想要的。
这里出现了接口的问题-如何访问派生类数据
首先你必须考虑"你的代码在哪里做这个"?处理整个inventory
的大部分代码应该只使用Item*
的内容,只使用Item
类的函数。
如果您有专门处理Weapon
对象的代码,创建Weapon
对象的地方(并插入inventory
),也可以将它们添加到另一个变量中,也许是
std::vector<Weapon*> weapons;
或类Warrior
的成员变量Weapon*
或类似的东西(但要注意,现在将有两个指向相同对象的指针,因此必须考虑所有权)。因此,只处理武器的代码(例如,Warrior
的成员函数)不会访问inventory
来获取Weapon
对象,它将始终直接使用Weapon*
。
如果出于某些原因,你必须编写一些代码来处理库存中的所有武器,那么编写一个函数,使用dynamic_cast
提取所有Weapon
对象(或者更好:使其成为迭代器函数),并在你需要访问所有武器时重用该函数。这样你就不用让动态强制转换弄乱你的代码,只要把它放在一个地方就可以了。
编辑:另一种选择(避免动态强制转换)是使用访问者模式,参见这篇文章。但我真的不喜欢那个帖子的答案,在呈现的形式中,它将暗示一个循环依赖"基础->访问者->派生->基础",这是一个糟糕的设计。
ValueType Weapon::getProprtyValue( PropertyType id ) {
switch( id ) {
case kWeaponProperty01: return m_weaponProperty01;
...
default: return Item::getPropertyValue( id );
}
}
您可以创建某种通用访问器方法,尽管它有一些限制,但它可能非常方便,特别是在内容编辑器,序列化等情况下
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- 如何在基类中定义静态接口,并确保该接口必须在派生类中实现
- C 结构实现派生接口
- 如何从接口获得派生类
- 接口会议派生的类功能而无需铸造
- 共享接口类和 C++ 派生类中的默认参数值
- 在派生类接口中隐藏基类的特定函数
- C++ 从嵌套类的接口派生
- C#派生的接口在C++中无法正常工作
- 定义多个派生接口成员
- 从接口派生的模板 - 多态性停止工作
- 具有显式派生方法的C++接口
- 从Const引用接口到派生类的转换
- 如何创建从另一个派生的两个ATL接口
- CLR 探查器:COM 样式的强制转换和从派生接口调用函数
- 具有扩展接口的派生类的集合.如何在没有动态强制转换的情况下访问派生接口
- c++:通过基类接口构造派生对象
- IUknown 派生接口上的虚拟析构函数
- 将从接口派生的类的实例添加到接口指针数组中
- 描述从多个接口派生的对象