Могу я бросать станд.:: вектор <Животное*> к станд.:: вектор <Собака*>, не смотря на каждый элемент?

Если вам не повезло иметь дело с окончаниями окон Windows, вам нужно удалить \r и \n

tr '[\r\n]' ' ' < $input > $output
8
задан Beau Simensen 24 July 2009 в 03:36
поделиться

5 ответов

Есть два варианта. Самый простой - использовать что-то вроде remove_copy_if . Я не могу объяснить, почему они так называют, но он копирует элементы из одного контейнера в другой, которые не удовлетворяют предикату. Вот основная идея (непроверенная):

struct IsDog : unary_function < Animal *, bool > {
  bool operator ()(Animal * animal) const {
    return dynamic_cast <Dog*> (animal);
  }
};

void foo (vector<Animal*> animals) {
  vector<Dog*> dogs;
  std::remove_copy_if (animals.begin ()
    , animals.end ()
    , back_inserter (dogs)
    , std::not1 ( IsDog () ) );  // not1 here negates the result of IsDog!


  // dogs now contains only animals that were dogs

}

Я полагаю, что способ взглянуть на remove_copy_if - это представить его как copy_unless .

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

class dog_iterator  // derive from std::iterator probably with bidirectinoal tag
{
private:
  vector<Animals*>::iterator getNextDogIter (vector<Animals*>::iterator iter) {
    while (iter != m_end) {
      if (0 != dynamic_cast<Dog*> (*iter)) {
        break;
      }
      ++iter;
    }
    return iter;
  }

public:
  dog_iterator (vector<Animals*>::iterator iter, vector<Animals*>::iterator end)
  : m_end (end)
  , m_iter (getNextDogIter (iter))
  {
  }

  // ... all of the usual iterator functions

  dog_iterator & operator++ ()
  {
    // check if m_iter already is at end - otherwise:
    m_iter = getNextDogIter (m_iter + 1);
    return *this;
  }
  // ...
};

Это очень грубо,

0
ответ дан 5 December 2019 в 15:25
поделиться

Вы можно использовать std :: transform . Он по-прежнему использует для () внутри, но вы получите двухстрочную реализацию:

#include <vector>
#include <algorithm>
using namespace std;

struct Animal { virtual ~Animal() {} };
struct Dog : Animal { virtual ~Dog() {} };

template<typename Target>
struct Animal2Target { Target* operator ()( Animal* value ) const { return dynamic_cast<Target*>(value); } };

void myDogCallback(vector<Animal*> &animals) {
{
    vector<Dog*> dogs;
    transform( animals.begin(), animals.end(), dogs.begin(), Animal2Target<Dog>() );
}
11
ответ дан 5 December 2019 в 15:25
поделиться

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

vector<Dog*> dogs;
vector<Animal*>::iterator iter;
Dog* dog;

for( iter = animals.begin(); iter != animals.end(); ++iter )
{
  dog = dynamic_cast<Dog*>(*iter);
  if( dog )
  {
    dogs.push_back( dog );
  }
}
0
ответ дан 5 December 2019 в 15:25
поделиться

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

См. CPP FAQ lite для получения дополнительной информации.

UPD Также см. Страница Stroustrup (поиск «Почему я не могу назначить вектор вектору?»)

0
ответ дан 5 December 2019 в 15:25
поделиться

Если вы говорите, что можете гарантировать, что каждый элемент действительно является собакой, тогда просто static_cast т.е.

void myDogCallback(vector<Animal*> &animals) {

    const vector<Animal*>::size_type numAnimals = animals.size();

    vector<Dog*> dogs;
    dogs.reserve( numAnimals );

    for ( vector<Animal*>::size_type i = 0; i < numAnimals; ++i ) {
        dogs.push_back(static_cast<Dog*>( animals[i] ));
    }
}

I обычно люди всегда получают резкую реакцию о том, что это плохо, и вы всегда должны использовать dynamic_cast , но на самом деле, если вы можете дать гарантии о типе, то это совершенно безопасно, и ИМО - разумный поступок. .

Кроме того, ваша гарантия будет означать, что новый вектор имеет тот же размер, поэтому зарезервируйте то же пространство, чтобы избежать выделения в каждом push_back . В качестве альтернативы петля I '

0
ответ дан 5 December 2019 в 15:25
поделиться
Другие вопросы по тегам:

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