"Двойной полиморфизм": шаблон двойной отправки или просто шаблон посетителя?
У меня есть
class BC_TOYFD
{
public:
BC_TOYFD( BS_TOYFD * pBS, BC2 dBC2 );
virtual ~BC_TOYFD( void ) ;
BS_TOYFD * _pBS ;
BC2 _dBC2 ;
double _PDA ; // store price down approximation
double _PUA ; // store price up approximation
virtual void COMPUTEBVDOWNFOR( PAYOFF_TOYFD * pPAYOFF, double * attime ) = 0 ;
virtual void COMPUTEBVUPFOR( PAYOFF_TOYFD * pPAYOFF, double * attime ) = 0 ;
};
из которого происходит
class DIRICHLET_TOYFD : public BC_TOYFD
{
public:
DIRICHLET_TOYFD( BS_TOYFD * pBS, BC2 dBC2 ) ;
~DIRICHLET_TOYFD( void ) ;
void COMPUTEBVDOWNFOR( PAYOFF_TOYFD * pPAYOFF, double * attime ) ;
void COMPUTEBVUPFOR( PAYOFF_TOYFD * pPAYOFF, double * attime ) ;
};
и я хотел бы методы
void DIRICHLET_TOYFD::COMPUTEBVDOWNFOR( PAYOFF_TOYFD * pPAYOFF, double * attime )
а также
void DIRICHLET_TOYFD::COMPUTEBVUPFOR( PAYOFF_TOYFD * pPAYOFF, double * attime )
делать вещи в соответствии с типом времени выполнения pPAYOFF, но не прибегая к
dynamic_cast<>
Как правило,
void DIRICHLET_TOYFD::COMPUTEBVDOWNFOR( PAYOFF_TOYFD * pPAYOFF, double * attime )
будет делать что-то вроде
_PUA = something if the runtime type of pPAYOFF (which is an abstract class) is for instance CALL_TOYFD
а также
_PUA = something else if the runtime type of pPAYOFF (which is an abstract class) is for instance PUT_TOYFD
где CALL_TOYFD и PUT_TOYFD являются открытыми производными от PAYOFF_TOYFD. И после, я хотел бы иметь возможность написать что-то вроде
double approx = bc->COMPUTEBVDOWNFOR( pPAYOFF, attime ) ;
где bc является экземпляром BC_TOYFD, и где pPAYOFF является указателем на PAYOFF_TOYFD, так что правильные типы для bc и pPAYOFF разрешаются во время выполнения.
Мне сказали использовать шаблон "двойная отправка" или "обратная двойная отправка", без каких-либо других намеков / точности. Я попытался реализовать это в этих рамках, не зная, как именно это сделать. Кстати, у меня будут "другие" классы, такие как DIRICHLET_TOYFD, производные от BC_TOYFD, для которых мне придется сохранить ту же проблему, что и ту, которую я пытаюсь решить, так что я предполагаю, что двойная диспетчеризация реализована в моем случае придется принять это ограничение во внимание.
Любая помощь будет оценена!
Большое спасибо!
1 ответ
Хорошо, после осознания того, что я полностью невежествен в задействованных шаблонах, и после небольшого изучения я наконец понял шаблон рассылки, и что шаблон посетителя действительно был шаблоном двойной рассылки.;-) Что касается фрагментов кода, которые я предложил, вот решение:
// fwd decls
class BOUNDARY_CONDITION_DIRICHLET ;
class BOUNDARY_CONDITION_NEUMANN ;
class PAYOFF
{
public:
virtual void on_call( BOUNDARY_CONDITION_DIRICHLET * pBOUNDARY_CONDITION_DIRICHLET ) = 0 ;
virtual void on_call( BOUNDARY_CONDITION_NEUMANN * pBOUNDARY_CONDITION_NEUMANN ) = 0 ;
};
////////////////////////////////////////////////////////
class BOUNDARY_CONDITION_DIRICHLET : public BOUNDARY_CONDITION
{
public:
void COMPUTE_APPROX( PAYOFF * pPAYOFF )
{
pPAYOFF->on_call( this ) ;
}
void on_visit( CALL * pCALL )
{
std::cout << "The code \"BOUNDARY_CONDITION_DIRICHLET->f(CALL);\" has been executed" << std::endl ;
}
void on_visit( PUT * pPUT )
{
std::cout << "The code \"BOUNDARY_CONDITION_DIRICHLET->f(PUT);\" has been executed" << std::endl ;
}
};
////////////////////////////////////////////////////////
class BOUNDARY_CONDITION_NEUMANN : public BOUNDARY_CONDITION
{
public:
void COMPUTE_APPROX( PAYOFF * pPAYOFF )
{
pPAYOFF->on_call( this ) ;
}
void on_visit( CALL * pCALL )
{
std::cout << "The code \"BOUNDARY_CONDITION_NEUMANN->f(CALL);\" has been executed" << std::endl ;
}
void on_visit( PUT * pPUT )
{
std::cout << "The code \"BOUNDARY_CONDITION_NEUMANN->f(PUT);\" has been executed" << std::endl ;
}
};
////////////////////////////////////////////////////////
class CALL : public PAYOFF
{
public:
void on_call ( BOUNDARY_CONDITION_DIRICHLET * pBOUNDARY_CONDITION_DIRICHLET )
{
pBOUNDARY_CONDITION_DIRICHLET->on_visit( this ) ;
}
void on_call( BOUNDARY_CONDITION_NEUMANN * pBOUNDARY_CONDITION_NEUMANN)
{
pBOUNDARY_CONDITION_NEUMANN->on_visit( this ) ;
}
};
////////////////////////////////////////////////////////
class PUT : public PAYOFF
{
public:
void on_call ( BOUNDARY_CONDITION_DIRICHLET * pBOUNDARY_CONDITION_DIRICHLET )
{
pBOUNDARY_CONDITION_DIRICHLET->on_visit( this ) ;
}
void on_call( BOUNDARY_CONDITION_NEUMANN * pBOUNDARY_CONDITION_NEUMANN )
{
pBOUNDARY_CONDITION_NEUMANN->on_visit( this ) ;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
BOUNDARY_CONDITION_DIRICHLET dBOUNDARY_CONDITION_DIRICHLET ;
BOUNDARY_CONDITION_NEUMANN dBOUNDARY_CONDITION_NEUMANN ;
CALL dCALL ;
PUT dPUT ;
BOUNDARY_CONDITION_DIRICHLET * pBOUNDARY_CONDITION_DIRICHLET = &dBOUNDARY_CONDITION_DIRICHLET ;
BOUNDARY_CONDITION_NEUMANN * pBOUNDARY_CONDITION_NEUMANN = &dBOUNDARY_CONDITION_NEUMANN ;
CALL * pCALL = &dCALL ;
PUT * pPUT = &dPUT ;
BOUNDARY_CONDITION * pBOUNDARY_CONDITION = pBOUNDARY_CONDITION_DIRICHLET ;
PAYOFF * pPAYOFF = pCALL ;
pBOUNDARY_CONDITION->COMPUTE_APPROX( pPAYOFF ) ;
pBOUNDARY_CONDITION = pBOUNDARY_CONDITION_DIRICHLET ;
pPAYOFF = pPUT ;
pBOUNDARY_CONDITION->COMPUTE_APPROX( pPAYOFF ) ;
pBOUNDARY_CONDITION = pBOUNDARY_CONDITION_NEUMANN ;
pPAYOFF = pCALL ;
pBOUNDARY_CONDITION->COMPUTE_APPROX( pPAYOFF ) ;
pBOUNDARY_CONDITION = pBOUNDARY_CONDITION_NEUMANN ;
pPAYOFF = pPUT ;
pBOUNDARY_CONDITION->COMPUTE_APPROX( pPAYOFF ) ;
system("pause") ;
return 0;
}
делать действительно то, что я ожидаю