Because of my device I can't use virtual functions. Suppose I have:
class Base { void doSomething() { } }; class Derived : public Base { void doSomething() { } }; // in any place { Base *obj = new Derived; obj->doSomething(); }
the obj->doSomething()
will call just the Base::doSomething()
Is there a way with Base *obj
, to call the doSomething
of the Derived
?
I know I can just put a virtual
before doSomething()
of Base
it solve the problem, but I'm limited by my device, the compiler doesn't support it.
If you don't use virtual functions, you don't understand OOP yet. Because the virtual function is intimately bound with the concept of type, and type is at the core of object-oriented programming, there is no analog to the virtual function in a traditional procedural language.
The main use of virtual function is to achieve Runtime Polymorphism. Runtime polymorphism can be achieved only through a pointer (or reference) of base class type. Also, a base class pointer can point to the objects of base class as well as to the objects of derived class.
Languages that are not object-oriented provide forms of polymorphism which do not rely on inheritance (i.e parametric polymorphism). Some of this is possible in Java through generics.
A virtual function is a special type of function that, when called, resolves to the most-derived version of the function that exists between the base and derived class. This capability is known as polymorphism.
You could down cast the base class pointer to the derived class and call the function.
Base* obj = new Derived; Derived* d = static_cast<Derived*>( obj ); d->doSomething();
Since doSomething()
is not declared virtual
, you should get the derived implementation.
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<Derived1*>(ptr)->*(fn_.derived1Fn_))(); case Derived2Type: return (static_cast<Derived2*>(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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With