Reputation: 3171
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());
What is the correct/clean way to call func2 without knowing which index corresponds to which class? Is there a convention to do such a thing? I also want to avoid using typeid.
Upvotes: 0
Views: 81
Reputation: 11513
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);
Upvotes: 1
Reputation: 229
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.
Upvotes: 1
Reputation: 6440
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
.
Upvotes: 2