Функция возвращает разные типы - PullRequest
0 голосов
/ 17 декабря 2018

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

До сих пор я пробовал различныефрагменты кода, например:

struct Base {
    std::string name = "Base";
};

struct Derived1 : Base {
    std::string name = "Derived1";
};

struct Derived2 : Base {
    std::string name = "Derived2";
};

template<class T>
T string_to_struct(std::string s) {
    if(s== "Derived1") {
        return Derived1();
    } else if(s == "Derived2") {
        return Derived2();
    } else {
        return Base();
    }
}

В основном я вызываю функцию:

void test2() {
    std::string s = "Derived1";
    auto bb = string_to_struct<Base>(s);
    std::cout << bb.name << std::endl;
}

Теперь я ожидал бы напечатать «Derived1», если s соответствует «Derived1», «Derived2 ", если оно равно" Derived2 "и так далее.Однако приведенный выше код не работает, и string_to_struct в любом случае возвращает экземпляр «Base».Как я могу решить это?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Лучший вариант в приведенном выше сценарии - использовать static_cast.Соответствующий фрагмент кода будет выглядеть следующим образом:

Base* string_to_struct7(std::string s) {
    if(s== "Derived1") {
        return new Derived1();
    } else if(s == "Derived2") {
        return new Derived2();
    } else {
        return new Base();
    }

, а затем для дальнейшей обработки:

auto t = string_to_struct7(s);
auto bb7 = static_cast<Derived1*>(t);
std::cout << bb7->name<< std::endl;

, что именно то, что я хочу получить.Производные члены класса теперь могут быть адресованы напрямую.

Ответ Макса Лангофа, конечно, также действителен.Использование просто Java-методов, подобных методам получения, работает, но имеет недостаток: они должны быть определены в каждом классе для каждого члена класса, что может быстро выйти из-под контроля.

Дополнительную информацию также можно найти здесь: C ++ Доступ к производному члену класса из указателя базового класса

РЕДАКТИРОВАТЬ: Третий подход заключается в использовании объекта-оболочки внутри производных классов и метода виртуального геттера.В настоящее время я не могу думать о недостатке - кроме того, чтобы быть уродливым.

0 голосов
/ 17 декабря 2018

string_to_struct всегда возвращает Base по значению (потому что вы просили об этом).Поскольку статический тип bb является Base, bb.name всегда относится к Base::name.А так как вы возвращаете по значению, динамический тип bb также всегда будет Base.

. Чтобы получить то, что вы хотите, вам нужно сделать две вещи:

  1. Не возвращать полиморфные объекты по значению Base.Если они созданы в функции, лучшим возвращаемым значением будет std::unique_ptr<Base>.Причина: вам нужны ссылки или указатели, чтобы полиморфия работала.

  2. Не используйте доступы, основанные на статическом типе объекта, например .name.Вы хотите использовать динамический тип из bb, который проще всего сделать с помощью виртуального метода, такого как:

    virtual std::string getName() const
    

    Это также более чистое решение, чем полагаться на (очень хрупкий) имя скрывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...