Because of my device I can\'t use virtual functions. Suppose I have:
class Base
{
void doSomething() { }
};
class Derived : public Base
{
void doSom
Sure you can do this; it's just not necessarily easy.
If there is a finite list of derived classes and you know what they are when you define the base class, you can do this using a non-polymorphic member function wrapper. Here is an example with two derived classes. It uses no standard library facilities and relies solely on standard C++ features.
class Base;
class Derived1;
class Derived2;
class MemFnWrapper
{
public:
enum DerivedType { BaseType, Derived1Type, Derived2Type };
typedef void(Base::*BaseFnType)();
typedef void(Derived1::*Derived1FnType)();
typedef void(Derived2::*Derived2FnType)();
MemFnWrapper(BaseFnType fn) : type_(BaseType) { fn_.baseFn_ = fn; }
MemFnWrapper(Derived1FnType fn) : type_(Derived1Type) {fn_.derived1Fn_ = fn;}
MemFnWrapper(Derived2FnType fn) : type_(Derived2Type) {fn_.derived2Fn_ = fn;}
void operator()(Base* ptr) const;
private:
union FnUnion
{
BaseFnType baseFn_;
Derived1FnType derived1Fn_;
Derived2FnType derived2Fn_;
};
DerivedType type_;
FnUnion fn_;
};
class Base
{
public:
Base() : doSomethingImpl(&Base::myDoSomething) { }
Base(MemFnWrapper::Derived1FnType f) : doSomethingImpl(f) { }
Base(MemFnWrapper::Derived2FnType f) : doSomethingImpl(f) { }
void doSomething() { doSomethingImpl(this); }
private:
void myDoSomething() { }
MemFnWrapper doSomethingImpl;
};
class Derived1 : public Base
{
public:
Derived1() : Base(&Derived1::myDoSomething) { }
private:
void myDoSomething() { }
};
class Derived2 : public Base
{
public:
Derived2() : Base(&Derived2::myDoSomething) { }
private:
void myDoSomething() { }
};
// Complete the MemFnWrapper function call operator; this has to be after the
// definitions of Derived1 and Derived2 so the cast is valid:
void MemFnWrapper::operator()(Base* ptr) const
{
switch (type_)
{
case BaseType: return (ptr->*(fn_.baseFn_))();
case Derived1Type: return (static_cast(ptr)->*(fn_.derived1Fn_))();
case Derived2Type: return (static_cast(ptr)->*(fn_.derived2Fn_))();
}
}
int main()
{
Base* obj0 = new Base;
Base* obj1 = new Derived1;
Base* obj2 = new Derived2;
obj0->doSomething(); // calls Base::myDoSomething()
obj1->doSomething(); // calls Derived1::myDoSomething()
obj2->doSomething(); // calls Derived2::myDoSomething()
}
(I originally suggested using std::function
, which does a lot of this work for you, but then I remembered it is a polymorphic function wrapper, so it necessarily uses virtual functions. :-P Oops. You can view the revision history to see what that one looked like)