Хранить разные объекты с одинаковой базой в одной очереди [дубликат]

В первом случае вы скрываете определение в родительском классе. Это означает, что он будет вызываться только в том случае, если вы имеете дело с объектом как дочерний класс. Если вы примените класс к его родительскому типу, будет вызван метод parent. Во втором случае метод переопределяется и будет вызываться независимо от того, был ли объект включен в качестве дочернего или родительского класса.

25
задан Andrei Bozantan 28 August 2011 в 21:32
поделиться

4 ответа

30
ответ дан Nicol Bolas 17 August 2018 в 19:25
поделиться

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

Если у вас есть:

std::vector<Dog> dogs;
std::vector<Cat> cats;

std::vector<Animal*> animals;

void addDog(Dog& dog, std::vector<Dog>& dogs, std::vector<Animal*>& animals) {
  dogs.push_back(dog);
  animals.push_back(&dog);
}

Затем все собаки и кошки хранятся в двух смежных областях памяти на куче.

1
ответ дан Brian Coleman 17 August 2018 в 19:25
поделиться
  • 1
    в точку. это называется объединенным подходом. Я собираюсь обобщить этот шаблон распределения в каком-то вспомогательном классе, который возьмет список типов шаблонов. другой шаблон, который я хотел бы предоставить, - это «чередующийся», который использует maxof (sizeof (все типы)), создавая вектор из variant. – v.oddou 7 April 2015 в 01:38
  • 2
    остерегайтесь того, что перераспределение векторов приведет к недействительности указателей – Mikel 4 June 2016 в 10:35
  • 3
    Это не работает вообще. Если кто-то хочет это сделать, вы должны использовать контейнер типа std :: deque, который не будет перемещать уже вставленные элементы (и недействительными указатели). – nondefault 11 April 2018 в 09:09

Я понимаю, что этот вопрос старый, но я нашел несколько довольно приемлемое решение.

Успение:

Вы знаете все производные классы заранее (учитывая ваше редактирование, это true).

Trick:

Использование boost :: variant ( http://www.boost.org/doc/libs/1_57_0/doc/html/variant. html )

Примеры классов:

class Animal {
public:
    virtual void eat() = 0;
};

class Cat : public Animal {
    virtual void eat() final override {
        std::cout << "Mmh, tasty fish!" << std::endl;
    }
};

class Dog: public Animal {
    virtual void eat() final override {
        std::cout << "Mmh, tasty bone!" << std::endl;
    }
};

Пример варианта / посетитель:

typedef boost::variant<Cat, Dog> AnimalVariant;

class AnimalVisitor : public boost::static_visitor<Animal&> {
public:
    Animal& operator()(Cat& a) const {
        return a;
    }

    Animal& operator()(Dog& a) const {
        return a;
    }
};

Пример использования:

std::vector<AnimalVariant> list;
list.push_back(Dog());
list.emplace_back(Cat());

for(int i = 0; i < 5; i++) {
    for(auto& v : list) {
        Animal& a = v.apply_visitor(AnimalVisitor());
        a.eat();
    }
}

Пример вывода

Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
5
ответ дан Draziw 17 August 2018 в 19:25
поделиться
  • 1
    да, это то, что я называю «чередующимся». подход, который является наиболее эффективным, когда все ваши классы имеют одинаковый размер. потому что заполнение является нулевым. Подход Брайана Колемана лучше всего, когда sizeof имеет большие различия среди типов. Это то, что можно оценить во время компиляции с помощью метафункции sigma (стандартное отклонение) и выбрать с помощью mpl::if_ или что-то еще, или использовать SFINAE или просто специализацию для реализации с использованием варианта для низкой сигмы и пулов для высоких сигм. – v.oddou 7 April 2015 в 01:43
  • 2
    Я действительно сделал что-то очень похожее на моем микроконтроллере, потому что все функции new не приветствуются ..... на микроконтроллерах не поддерживается только повышение, поэтому я написал свой собственный класс variant – DarthRubik 10 July 2016 в 21:56

Возможно, вы могли бы сделать что-то с простым классом-оболочкой для объединения, содержащего супер-набор данных, необходимых для каждого случая. Это будет содержать указатель на общие стратегии объекты, содержащие код для разных типов поведения. Таким образом, кошка является объектом класса PolyAnimal с видамиName = «cat», PredatorFeedingStrategy и т. Д.

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

0
ответ дан soru 17 August 2018 в 19:25
поделиться
  • 1
    Решение со схемой стратегии было моей второй идеей (интересно, как шаблоны проектирования появляются, когда вы пишете код, даже когда вы не знаете о них :)), но когда я начал реализовывать решение, он начал чувствовать себя немного неестественным. Конечно, после нескольких мыслей об этом, я, вероятно, поеду с пользовательскими распределителями. – Andrei Bozantan 29 August 2011 в 07:27
Другие вопросы по тегам:

Похожие вопросы: