我想编写一个函数,将“ Armor”类的对象作为参数,但是,当我调用该函数时,我改用基类“ Item”的对象。当然,我使用的这个对象即使仅被视为“物品”,也可能是“装甲”。仅当我确定它是“装甲”时,才想调用该函数。
就我而言,我将物品存储在矢量中(这些物品可以是装甲)。我想从向量中获取该物品并用它调用函数(装备该物品,我知道这是一件盔甲)。
class Item{
};
class Armor : public Item{
};
void equipArmor(Armor armor){ //Armor class argument
//Equip the armor
}
int main(){
vector<Item> items;
Armor a;
items.push_back(a);
equipArmor(items[0]); //Call function with an "Item" as an argument (even though it is in fact also an "Armor")
}
答案 0 :(得分:2)
您的向量为Item
。当您push_back
到Armor
时,它将sliced变成Item
。因此,向量中不再有Armor
,而只有普通的Item
。
这就是为什么您的代码无法正常工作的原因。首先,您不能使用equipArmor()
来调用Item
函数,因为它期望Armor
并且向下转换从不隐含。但是即使可以,您始终将传递Item
值,而永远不会传递Armor
值。
要解决您的问题,您需要使用指针(更好的智能指针)或引用。
要能够使用polymorphic类型并进行运行时类型确定,首先需要在基类中至少具有一个虚函数:
class Item{
public:
virtual ~Item() {}
};
现在让我们将向量设为shared pointers的向量。令人高兴的是,这些对象将确保在不再在任何共享指针中使用对象时将其销毁。因此,减少了内存管理的麻烦,而减少了rule of 3的麻烦:
vector<shared_ptr<Item>> items;
shared_ptr<Item> a = make_shared<Armor>();
items.push_back(a);
shared_ptr<Item> i = make_shared<Item>();
items.push_back(i);
equipArmor(items[0]); // lets just try the two possible cases
equipArmor(items[1]);
最后,在您的函数中,您可以使用dynamic_pointer_cast
以安全的方式感知实类型并采取相应的行动:
void equipArmor(shared_ptr<Item> item){ //Armor class argument
shared_ptr<Armor> a = dynamic_pointer_cast<Armor>(item);
if (a) {
cout << "Armor"<<endl;
}
else cout << "Item"<<endl;
}
备注
如果您的类型不是多态的,那么您将无法dynamic_pointer_cast
。您仍然可以使用static_pointer_cast
进行强制转换,但这是有风险的,因为它要求您确定转换的智能指针的类型正确。
如果您更喜欢原始指针,则可以应用相同的原理,但是请分别使用dynamic_cast
或static_cast
。但是,static_cast
再次要求您绝对确定类型。如果您有一个充满随机项目的向量,怎么办?
答案 1 :(得分:1)
您想从基类(Item
)转换为子类(Armor
)。这是不可能的。
如果items
是指向Item
的指针的向量,则可以执行此操作。如果确定基础对象实际上是Item *
,则可以将Armor *
强制转换为Armour
。
int main(){
std::vector<Item *> items;
Armor a;
items.push_back(&a);
// This only works if items[0] points to an Armor object
equipArmor(*static_cast<Armor *>(items[0]));
}