Как правильно инициализировать другой производный класс в операторе switch? - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть следующий код со структурой иерархии классов базового класса Base и несколькими производными классами Derived1, Derived2, Derived3 ... и т. Д.

switch(i){
    case 1:{
        Derived1* d1;
        generateD1(d1);
        otherFunc(d1); //function signature is otherFunc(Base*)
        break;
    }
    case 2:{
        Derived2* d2;
        generateD2(d2);
        otherFunc(d2);
        break;
    }
    ...  //goes on for many cases
}

Как использовать наследованиемеханизм улучшения вышеуказанных кодов?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

FYI, в дополнение к решению @SidS, мы также можем извлечь процесс генерации в виде простой функции, которая возвращает указатель Base следующим образом.Здесь я также использую std::unique_ptr, что делает наш код более безопасным с семантикой RAII, и тогда вы можете опустить вызов delete b:

#include <stdexcept>
#include <memory>

std::unique_ptr<Base> create(int i) // C++11
{
    switch(i)
    {
        case 1:
            return std::make_unique<Derived1>(); // C++14
            break;
        case 2:
            return std::make_unique<Derived2>();
            break;
        default:
            throw std::logic_error("unsupported.");
    }
}

Тогда сторона вызова будет более простой, как показано ниже:

DEMO

auto b = create(i);
b->generate();
b->other();
0 голосов
/ 07 февраля 2019

Примерно так:

class Base
{
    public:
        virtual ~Base() {}

        virtual void generate() = 0 {}

        virtual void other() = 0 {}
};

class Derived1 : public Base
{
    public:
        virtual void generate() override {}

        virtual void other() override {}
};

class Derived2 : public Base
{
    public:
        virtual void generate() override {}

        virtual void other() override {}
};

int main()
{
    int i;
    Base *b;
    switch(i)
    {
        case 1:
            b = new Derived1;
            break;
        case 2:
            b = new Derived2;
            break;
        ...
    }
    b->generate();
    b->other();
    ...
    delete b;
    return 0;
}

Вы можете отказаться от метода generate() и просто использовать конструкторы:

class Base
{
    public:
        virtual ~Base() {}

        virtual void other() = 0 {}
};

class Derived1 : public Base
{
    public:
        Derived1() {}

        virtual void other() override {}
};

class Derived2 : public Base
{
    public:
        Derived2() {}

        virtual void other() override {}
};

int main()
{
    int i;
    Base *b;
    switch(i)
    {
        case 1:
            b = new Derived1;
            break;
        case 2:
            b = new Derived2;
            break;
        ...
    }
    b->other();
    ...
    delete b;
    return 0;
}
...