Интерфейсы, пропускающие контейнер Интерфейсов - PullRequest
0 голосов
/ 28 ноября 2018

Если есть интерфейс с сигнатурой метода, как показано ниже,

class Interface2
{
public:
    virtual ~Interface2() {}
    virtual uint getId() = 0;
    virtual std::string getName() = 0;
};

class Interface
{
public:
    virtual ~Interface(){}
    virtual std::list<Interface2*> getData(uint id) = 0;
};

Таким образом, в основном цель getData(uint id) состоит в том, чтобы открыть внутреннее хранилище Interface2 интерфейсов

Когдареализуя конкретный класс Interface, он будет хранить хранилище объектов из конкретных классов Interface2.

Например, следующий способ может быть способом реализации этих интерфейсов

class Interface2Imp : public Interface2
{
public:
    uint getId() { return id;}
    std::string getName() { return name;}

private:
    uint id;
    std::string name;
};

class InterfaceImp : public Interface
{
public:
    std::list<Interface2*> getData(uint id)
    {
        std::list<Interface2*> returnList;
        std::list<Interface2Imp> & a = storage[id];
        for(auto & it : a)
        {
            returnList.push_back(&it);
        }
        return returnList;
    }

private:
    std::map<int, std::list<Interface2Imp> > storage;
}

Но, глядя на то, как реализован getData(uint id), мы видим, что он перебирает свое внутреннее хранилище, а затем снова заполняет его списком интерфейсов, который выглядит дорогостоящим (и некрасивым).

Есть лилучший способ выставить внутренние данные интерфейса, которые также могут быть представлены как интерфейсы?

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

То, что у вас есть, это в основном multimap<int, Interface2Imp>, но с изюминкой: внешним пользователям нужно видеть Interface2*, а не Interface2Imp&.

Это пример использования модели для адаптеров итераторов .Вы можете украсть один из Boost или написать свой собственный.В последнем случае вам нужен класс, который содержит действительный член multimap<int, Interface2Imp *>::const_iterator, перенаправляет большинство методов iterator-y напрямую и адаптирует только operator *() и operator ->() немного по-другому (возвращает то, что внутренний член возвращает, но передается вуказатель / ссылка на базовый класс).

Если вы не хотите упоминать Interface2Imp даже в приватной части вашего адаптера итератора, скрывайте его идиомой Pimpl.

0 голосов
/ 28 ноября 2018

Альтернативным решением было бы хранить интеллектуальные указатели для экземпляров реализации интерфейса на 1-м месте:

class InterfaceImp : public Interface
{
public:
    const std::list<std::shared_ptr<Interface2>>& getData(uint id)
    {
        return storage[id];
    }

private:
    std::map<uint, std::list<std::shared_ptr<Interface2>> > storage;
}

Если вам нужен доступ к экземплярам Interface2Imp для доступа к функциям или данным, это не видно черезInterface2 вы всегда можете использовать static_cast<Interface2Imp*> с этими экземплярами, потому что ваш класс InterfaceImp знает, что использовалось для создания экземпляров std::shared_ptr<Interface2>.
Вы даже можете выполнять полные запросы времени выполнения, используя dynamic_cast<Interface2*>, если этонеобходимо и не влияет на производительность вашего приложения.

0 голосов
/ 28 ноября 2018

в том виде, в каком оно стоит, итерация и копирование должны быть выполнены.Класс хранит список экземпляров X, вам нужен список указателей на экземпляры X. Это две разные вещи.Возможно, вы могли бы сделать кое-что из std :: алгоритма и т. Д., Но это не меняет того факта, что итерация и клонирование должны быть выполнены.

Как насчет изменения интерфейсов и реализации.Заставьте класс InterfaceImp сохранить список shared_ptr в Interface, а метод getData вернет список shared_ptrs.Теперь контейнер может напрямую возвращать свои данные.(Также вы не перемещаете необработанные указатели)

Сказав, что то, что у вас есть в данный момент, является лучшей инкапсуляцией.Вы не предоставляете свои внутренние данные вызывающей стороне, вы клонируете их.

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