#c #oop #polymorphism #language-lawyer
#c #ооп #полиморфизм #язык-юрист
Вопрос:
Итак, у меня изначально был этот код на C:
void stub() { /* do nothing */ }
static void (*mlutiplylasttwovalues)() = stub, (*dividelasttwovalues)() = stub, (*modulolasttwovalues)() = stub;
void mlutiplylasttwovaluesconstexpr()
{
/*do multiply*/
}
void dividelasttwovaluesconstexpr()
{
/*do divide*/
}
void modulolasttwovaluesconstexpr()
{
/*do modulo */
}
void switchtoconstantexpr()
{
mlutiplylasttwovalues = mlutiplylasttwovaluesconstexpr;
dividelasttwovalues = dividelasttwovaluesconstexpr;
modulolasttwovalues = modulolasttwovaluesconstexpr;
}
void switchoutofconstantexpr()
{
mlutiplylasttwovalues = stub;
dividelasttwovalues = stub;
modulolasttwovalues = stub;
}
Идея заключалась в том, чтобы, как вы, вероятно, можете сказать, иметь функции, которые делают что-то только в определенном контексте.
Однако, поскольку я писал на C , я решил переписать его следующим образом:
struct basehndl
{
virtual void mlutiplylasttwovalues()
{/* do nothing */ }
virtual void dividelasttwovalues()
{/* do nothing */ }
virtual void modulolasttwovalues()
{/* do nothing */ }
};
struct handlecnstexpr : basehndl
{
virtual void mlutiplylasttwovaluesconstexpr()
{
/* do multiply*/
}
virtual void dividelasttwovaluesconstexpr()
{
/* do divide*/
}
virtual void modulolasttwovaluesconstexpr()
{
/* do modulo*/
}
};
basehndl hndl{};
И тогда вместо switchtoconstantexpr
и switchoutofconstantexpr
я буду использовать:
hndl.~basehndl();
new (amp;hndl) handlecnstexpr{};
И соответственно:
((handlecnstexpr *)amp;hndl)->~handlecnstexpr();
new (amp;hndl) basehndl{};
Мой вопрос — является ли это допустимым стандартным кодом C или, если нет, есть ли лучший способ C сделать то, чего я пытаюсь достичь, без использования динамического распределения, как изначально.
Комментарии:
1. Я не могу найти в стандарте C ничего, что гарантировало бы, что оба класса должны иметь одинаковый размер и выравнивание, поэтому это злоупотребление размещением new не гарантируется как определенное поведение. Правильная, правильная, типобезопасная реализация этого будет просто использоваться
std::variant
, и пусть она беспокоится о безопасности типов.2. Просто создайте две отдельные переменные, одну типа
basehndl
и другуюhandlecnstexpr
, иbasehndl*
указатель, который указывает на одну или другую.