在运行时不使用虚函数从基类方法访问派生类方法

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

本文关键字:类方法 基类 访问 派生 函数 运行时      更新时间:2023-10-16

我有以下代码示例。一个基类和两个派生类,每个派生类都有自己的函数。Function1和function2)。function1和function2在基类中都不是虚函数。我不能改变这个,因为这些类已经实现了。

#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;
};

我现在正在努力实现以下目标。我想在运行时决定要使用哪个派生类。此外,我希望通过只使用对象b从基类方法调用它们。否则,我将不得不为我允许在运行时输入的每个选项重写我的程序(实际上,我有相当多的类可以从中选择)。

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;
}

是否有可能做(*)代码行没有一个if(option == 1)和if(option == 2)循环?我不能使用任何虚拟功能,因为它没有实现…对于这个问题是否有更优雅的解决方案?

您可能会编写一个使用指针初始化的包装器,并在一天结束时在内部解决动态分派,但我不确定这是否值得麻烦。如果你能修改这三个类型,这就是你应该做的,其他的都只是一个讨厌的hack。

使用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
}

请注意,这是一个令人讨厌的技巧,并且它将变得很难很容易地维护。