开发者

Accessing derived class method from base class method without virtual functions on run time

I have the following code sample. One base class and two derived classes with each their own functions (resp. function1 and function2). Neither function1 and function2 are virtual in the base class. I can not change this as these classes are already implemented.

#include <iostream>    
class Base
{
public:
    Base(){}
    Base(int val) : m_base(val){}
    virtual ~Base(){}
    //base class methods
private:
    int m_base;
};

class Derived1 : public Base
{
public:
    Derived1(int val) : m_derived1(val){}
    ~Derived1(){}
    void print1(){std::cout << "Using Derived 1 class method" << std::endl;};
private:
    int m_derived1;
};

class Derived2 : public Base
{
public:
    Derived2(int val) : m_derived2(val){}
    ~Derived2(){}
    void print2(){std::cout << "Using Derived 2 class method" << std::endl;};
private:
    int m_derived2;
};

I'm trying to achieve the following now. I want to decide on run time which derived class I want to use. Moreover I would like to call them from the base class method by only using the object b. Otherwise I would have to rewrite my program for every option I allow to enter at runtime (in practice I have quite some classes from which I can choose from).

int main()
{
    int 开发者_开发问答option;
    std::cin >> option;

Base* b = new Base(5);

Derived1* d1 = new Derived1(5);
Derived2* d2 = new Derived2(5);

d1->print1(); //obviously this works
d2->print2(); //obviously this works

//In reality I thus have a function in d1 and d2 which is not present in b
//I have to decide on runtime which class I need to use

if(option == 1)
{
    b = d1;
}
else if(option == 2)
{
    b = d2;
}

/*
Rest of program ...
    b->invokeMethod;
    // ... //
    b->invokeMoreMethods;
*/

//Call derived functions on base object

//b->print1(); //fails obviously
if(option == 1)
{
    dynamic_cast<Derived1*>(b)->print1(); //will work if option == 1 is specified (*)
}
if(option == 2)
{
    dynamic_cast<Derived2*>(b)->print2(); //will work if option == 2 is specified (*)
}

return 0;
}

Is it possible to do the (*) code lines without an if(option == 1) and if(option == 2) loop? I can't make use of any virtual functionality as it is not implemented... Are there more elegant solutions to this problem?


Potentially you could write a wrapper that is initialized with either pointer and which at the end of the day resolves the dynamic dispatch internally, but I am not sure it is worth the trouble. If you can modify the three types, that is what you should aim to do, everything else is just a nasty hack.

Hack with std::/boost::function:

int main() {
    Base * b = 0;                    // You were leaking a Base object here
    boost::function< void () > f;
    ...
    if ( option == 1 ) {
       Derived1 d1 = new Derived1;   // Only instantiate the object you will use
       b = d1;
       f = boost::bind( &Derived1::print1, d1 );
    } else if ( option == 2 ) {
       Derived2 d2 = new Derived2;
       b = d2;
       f = boost::bind( &Derived2::print2, d2 );
    }
    ...
    f(); // will call either d1->print1(), or d2->print2()
    ...
    delete b;                      // should really use a smart pointer but I left
                                   // the raw pointer to minimize changes
}

Note that this is a nasty trick, and that it will become hard to maintain quite easily.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜