Jim said:
I'm passing an object to another type of object, and would like it to
have access to a public static function contained in the original
object's class, is that possible? I have two types of object each
derived from a base class, each with their own static function of the
same name.
I got somewhat interested by this problem (although the right
way to fix it is probably to use non-static virtual member
functions). Not a C++ expert here, so take everything below with
a grain of salt.
There seems to be a way to achieve this without modifying the
"library" code, but it's ugly-ish and will require extensive
changes to the client code:
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <cassert>
class Base {
public:
virtual ~Base() {}
virtual std::string getTypeInfo() = 0;
};
class Derived1 : public Base {
public:
std::string getTypeInfo() { return "Derived1"; }
static void doStuff() {
std::cout << "Stuff appropriate for Derived1" << std::endl;
}
};
class Derived2 : public Base {
public:
std::string getTypeInfo() { return "Derived2"; }
static void doStuff() {
std::cout << "Stuff appropriate for Derived2" << std::endl;
}
};
class BaseWrapper {
public:
virtual void doStuff() = 0;
};
template<class T> class Wrapper : public T, public BaseWrapper {
public:
void doStuff() { T::doStuff(); }
};
int main() {
std::vector<Base *> objects;
objects.push_back(new Wrapper<Derived1>);
objects.push_back(new Wrapper<Derived2>);
objects.push_back(new Derived2);
for (std::vector<Base *>::iterator i = objects.begin();
i != objects.end(); ++i) {
std::cout << (*i)->getTypeInfo() << std::endl;
BaseWrapper *bw = dynamic_cast<BaseWrapper *>(*i);
assert(bw != NULL);
bw->doStuff();
delete *i;
}
return 0;
}
As you can see, you'll have to use Wrapper<Derived> objects
instead of Derived objects, and you'd probably want to check
explicitly whether your cast worked to avoid all sorts of mayhem
imminent upon dereferencing a NULL pointer.
It becomes a little more pleasing to the eye if your Derived
classes use virtual inheritance from Base (or if that's a change
you can, and are willing to make):
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
class Base {
public:
virtual ~Base() {}
virtual std::string getTypeInfo() = 0;
};
class Derived1 : public virtual Base {
public:
std::string getTypeInfo() { return "Derived1"; }
static void doStuff() {
std::cout << "Stuff appropriate for Derived1" << std::endl;
}
};
class Derived2 : public virtual Base {
public:
std::string getTypeInfo() { return "Derived2"; }
static void doStuff() {
std::cout << "Stuff appropriate for Derived2" << std::endl;
}
};
class BaseWrapper : public virtual Base {
public:
virtual void doStuff() = 0;
};
template<class T> class Wrapper : public T, public BaseWrapper {
public:
void doStuff() { T::doStuff(); }
};
int main() {
std::vector<BaseWrapper *> objects;
objects.push_back(new Wrapper<Derived1>);
objects.push_back(new Wrapper<Derived2>);
for (std::vector<BaseWrapper *>::iterator i = objects.begin();
i != objects.end(); ++i) {
std::cout << (*i)->getTypeInfo() << std::endl;
(*i)->doStuff();
delete *i;
}
return 0;
}
Of course, this way you'll also have to use BaseWrapper instead
of Base, but at least the cast is no longer there.
Please correct me if there is anything I'm missing or
misinterpreting.