Различать производные объекты в векторе базовых указателей в C ++ - PullRequest
0 голосов
/ 22 мая 2018

В продолжение этого вопроса Вектор / контейнер, состоящий из различных производных объектов в C ++ Я попытался улучшить свой код.Теперь я храню указатели на мои производные объекты в одном векторе, но я не уверен, как получить доступ к их функциям-членам, специфичным для производного класса и , чтобы разделить один вектор на подвекторы изкаждый соответствующий производный тип.

#include <vector>
#include <memory> // for unique_ptr
#include <iostream>

using namespace std;

class Fruit {};
class Banana: public Fruit { void cout_banana() { cout << "i am a banana" << endl; } };
class Apple : public Fruit { void cout_apple() { cout << "i am an apple" << endl; } };

class FruitBox
{
    vector<unique_ptr<Banana>> vec_banana;
    vector<unique_ptr<Apple>>  vec_apple;

public:
    FruitBox(const vector<unique_ptr<Fruit>> &fruits)
    {
        for (const unique_ptr<Fruit> &f : fruits)
        {
            // How to figure out if f is Banana or Apple and then
            // 1) Print either cout_banana or cout_apple
            // 2) Store/Move f in either vec_banana or vec_apple
        }
    }
};

void main()
{
    vector<unique_ptr<Fruit>> inputs;
    inputs.emplace_back(new Banana());
    inputs.emplace_back(new Apple());

    FruitBox fbox = FruitBox(inputs);
}

1 Ответ

0 голосов
/ 22 мая 2018

Я думаю, что ваша проблема не в реализации как таковой (проверка фактического класса была бы возможна с использованием dynamic_cast, но я не буду вдаваться в подробности здесь, так как это не нужно), а скорее в ваше понимание ориентации объекта впервое место - по крайней мере, в этом конкретном примере.

Принцип замены Лискова *1005* гласит, что "если S является подтипом T, то объекты типа T могут быть заменены объектамитипа S (т.е. объект типа T может быть заменен любым объектом подтипа S). " Здесь это не так.

Вместо определения cout_xyz в ваших подклассах, выследует написать void cout_fruit() как абстрактный метод в class Fruit и переопределить его в подклассах.

class Fruit { public: virtual void cout_fruit() = 0; };
class Banana: public Fruit { public: void cout_fruit() override { cout << "i am a banana" << endl; } };
class Apple : public Fruit { public: void cout_fruit() override { cout << "i am an apple" << endl; } };
// [...]

Тогда для каждого фрукта вы можете просто вызвать f->cout_fruit().

...