Если я правильно понимаю, что вы пытаетесь достичь, вам может быть полезно взглянуть на шаблон «двойной отправки»:
двойная диспетчеризация - это особая форма множественной диспетчеризации и механизм, который отправляет вызов функции различным конкретным функциям в зависимости от типов времени выполнения двух объектов, участвующих в вызове ( source )
Грубо: ваш клиентский объект вызывает "execute" для целевого объекта:
target.execute(client);
целевой объект вызывает метод для промежуточного объекта, который действует как расширенная виртуальная таблица (фактически, таблица с несколькими отправлениями):
dispatchTable.execute(client, *this); //-- target calls this
и таблица отправки по очереди вызывает правильный метод (с полной подписью) для целевого объекта:
<get arguments from client>
target.specific_execute(arguments)
В качестве альтернативы и, возможно, более удобно, механизм таблицы диспетчеризации может быть предложен самим клиентским объектом. Итак, target::execute
звонит:
client.execute(target);
и client::execute(target)
наконец вызовут:
target.specific_execute(args);
Клиентский класс предоставит набор перезагруженных execute
методов, каждый для определенного целевого типа. Метод будет инкапсулировать знания о специфике этого объекта execute
аргументов.
Это может потребовать некоторого рефакторинга вашего проекта (при первом подходе клиент должен предложить способ получения аргументов для вызова), и это может выглядеть как реализация довольно низкого уровня (таблица диспетчеризации), но это чистый подход, ИМО.
class Client;
struct Base {
virtual void dispatch(Client& c);
void execute(Base& b) {
std::cout << "void execute(Base&)" << std::endl;
}
};
struct DerivedA : public Base {
void exec(int i){
/*do something with i*/
std::cout << "void execute(int i)" << std::endl;
}
};
struct DerivedB : public Base {
void exec(int i, float f)
{
std::cout << "void execute(int i, float f)" << std::endl;
}
};
struct Client {
int i;
float f;
void execute(Base& obj) {
}
void execute(DerivedA& obj) {
obj.exec(i);
}
void execute(DerivedB& obj) {
obj.exec(i, f);
}
void doTest() {
Base* b1 = new DerivedA();
Base* b2 = new DerivedB();
b1->dispatch(*this);
b2->dispatch(*this);
}
};
void Base::dispatch(Client& c) {
c.execute(*this);
}
void DerivedA::dispatch(Client& c) {
c.execute(*this);
}
void DerivedB::dispatch(Client& c) {
c.execute(*this);
}
int main (int argc, char * const argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
Client c;
c.doTest();
return 0;
}