class Base {
virtual void func1();
}
class Derived : Base {
void func1();
void func2();
}
vector<Base *> vec;
vec.push_back(new Base()), vec.push_back(new Derived());
在没有知道哪个索引对应哪个类的情况下调用func2 的正确/干净方法是什么?做这样的事情会有约定吗?我还想避免使用 typeid 。
答案 0 :(得分:2)
In your case the objects are sliced, as mentioned in king_nak's answer, so there's no safe way to call func2()
.
But you can store pointers to Base instead of Base objects - in this case you can use dynamic_cast
:
std::vector<Base*> vec;
vec.push_back(new Base());
vec.push_back(new Derived());
for (auto obj : vec)
{
Derived* d = dynamic_cast<Derived*>(obj);
if (d)
{
d->func2();
}
}
Some info on dynamic_cast
: link
PS: Also, if you want to call function func2()
on Base
objects, I think it makes sense to add a stupid implementation to Base
class and make the function virtual
.
答案 1 :(得分:1)
This function will take one of said pointers and call func2 if possible, and simply return false otherwise
bool CallFunc2(Base* Bae){
Derived* Der;
if (Der = dynamic_cast<Derived*>(Bae))
{Der->func2(); return true;}
else
return false;
}
This works on the principle that dynamic_cast returns a null pointer if the object being cast cannot be converted.
答案 2 :(得分:1)
If you don't want to use RTTI at all (including dynamic_cast
), you could simulate its behaviour like Qt does it with qgraphicsitem_cast
Outline:
class Base {
public:
enum { Type = 0 };
virtual int type() { return Type; }
};
class Derived : public Base {
public:
enum { Type = 1 };
int type() { return Type; }
};
template<typename T>
inline T myobject_cast(Base *b) {
if (b) {
// Requires C++11
if (int(std::remove_pointer<T>::type::Type) == b->type()) {
return static_cast<T>(b);
}
/* Pre C++11 (might be UB, but works on many compilers, OpenSource and Commercial)
if (int(static_cast<T>(0)->Type) == b->type()) {
return static_cast<T>(b);
}
*/
}
return NULL;
}
// use:
Base *b = new Base;
Base *d = new Derived;
Derived *o1 = myobject_cast<Derived*> (b); // NULL
Derived *o2 = myobject_cast<Derived*> (d); // d
Each class would require a unique Type
member for this to work.
Be aware that this will not work with "intermediate" classes in the hierarchy. Only the actual, most derived type will can be cast to (e.g. a DerivedDerived
cannot be cast to a Derived
, or Base
for that matter).
You might also find an overload for const handy:
template<typename T> inline T myobject_cast(const Base *b)
{ return (b && int(static_cast<T>(0)->Type) == b->type()) ? static_cast<T>(p) : 0; }
const Base *cb = new Derived;
const Derived *co = myobject_cast<const Derived *>(cb);