Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get polymorphic behavior without using virtual functions?

Tags:

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.

like image 693
okami Avatar asked Sep 29 '10 02:09

okami


People also ask

What happens if we don't use a virtual function in the inheritance?

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.

What is the necessity of virtual function in polymorphism?

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.

Is polymorphism possible without objects?

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.

Is virtual function part of polymorphism?

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.


2 Answers

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.

like image 107
paxos1977 Avatar answered Oct 27 '22 04:10

paxos1977


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)

like image 28
James McNellis Avatar answered Oct 27 '22 03:10

James McNellis