class Base
{
public:
Base();
virtual ~Base();
int getType();
protected:
int type;
};
class DerivedA : public Base
{
public:
DerivedA() { this->type = 1; };
~DerivedA();
int getA() { return 1;};
};
class DerivedB : public Base
{
public:
DerivedB() { this->type = 2; };
~DerivedB();
int getB() { return 2;};
};
有一个包含两个派生类的对象的向量,然后能够访问特定于子的方法。
int main()
{
typedef boost::ptr_vector<Base> BasePtr;
BasePtr vec;
// Fill vec with some stuff
vec.push_back(new DerivedA());
vec.push_back(new DerivedB());
vec.push_back(new DerivedA());
vec.push_back(new DerivedB());
typedef BasePtr::iterator BaseIter;
for ( BaseIter it = vec.begin(); it != vec.end(); it++ ) {
if (it->getType() == 1) {
std::cout << it->getA() << '\n';
} else {
std::cout << it->getB() << '\n';
}
}
return 0;
}
显然,“它”不被识别为DerivedA或DerivedB,因此无法访问特定于子的方法。 需要某种形式的演员表,所以我想问题是:
也许有更好的方法来构建整个场景?
修改 似乎我有点不清楚。派生类中方法的目的是根本不同的。 考虑具有派生类Armor和Weapon的基类Item。
在这个例子中你可以看到为什么,例如,Weapon有一个函数getDamage()可能会返回一个浮点数。
Armor不需要这个功能,甚至没有类似的东西。
在此示例中,您可以将向量视为可以包含任何数量和类型的项目的库存。甚至可能是有堆叠和一些使用的物品(可能是魔药)
答案 0 :(得分:2)
如果你必须转换为派生,那么这意味着你的设计很糟糕。
但如果你真的必须这样做(把它放在for循环中):
DerivedB * typeB = dynamic_cast< DerivedB * >( &*it );
if ( typeB != nullptr )
{
std::cout << typeB->getB() << '\n';
}
更好的方法是将getB()
添加到接口,并在DerivedA中实现它(它可以返回一些虚拟值,或者如果确实需要则抛出)。
答案 1 :(得分:1)
Casting是一个非常难看的解决方案,而不是C ++。相反,你应该使用虚拟功能。
类似的东西:
class Base
{
public:
virtual int get() = 0;
// ...
};
class DerivedA : public Base
{
public:
int get() { return 1;};
};
class DerivedB : public Base
{
public:
int get() { return 2;};
};
然后无需额外的类型,您只需拨打it->get();
。
答案 2 :(得分:1)
您可以使用dynamic_cast,如下所示。
for ( BaseIter it = vec.begin(); it != vec.end(); it++ )
{
DerivedA* dA = dynamic_cast<DerivedA*>(it);
if(dA != NULL)
{
// Do whatever for DerivedA
}
// Similarly check for DerivedB
}
除了设计接口以利用多态性之外,没有简单的方法。即,在基类中定义函数签名并在派生类中实现它们。上面的for循环,理想情况下不应该试图知道容器项的类型。如果不知道getA()和getB()表示的实际函数是什么,就不可能对此进行评论。