问题描述
||
我有以下代码示例。一个基类和两个派生类具有各自的功能(分别为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
}
请注意,这是一个令人讨厌的把戏,很难轻易维护。