Является ли моя повторная реализация этого фрагмента C в C правильной?

#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* указатель, который указывает на одну или другую.