J'ai une classe de base avec plusieurs classes en prolongant. J'ai des utilitaires de bibliothèque génériques qui créent un vecteur contenant des pointeurs sur la classe de base afin que l'une des sous-classes fonctionnera. Comment puis-je lancer tous les éléments du vecteur à une classe enfant spécifique? Ma solution naïve ressemblerait à ceci: P> // A method is called that assumes that a vector containing
// Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
// I want to cast all of the elements of animals to
// be dogs.
vector<Dog*> dogs;
vector<Animal*>::iterator iter;
for ( iter = animals.begin(); iter != animals.end(); ++iter ) {
dogs.push_back(dynamic_cast<Dog*>(*iter));
}
}
7 Réponses :
Votre code comme écrit mettra un tas de pointeurs nuls dans votre vecteur de chiens lorsque le vecteur d'animaux contient d'autres spécialisations animales.
Il n'est généralement pas très bon d'utiliser dynamic_cast pour la sous-emploi. Vous devez probablement refroidir votre code afin que vous n'ayez pas besoin d'utiliser la radiographie explicite. P>
voir FAQ CPP Lite pour plus d'autres informations. p>
upd fort> aussi, voir STROSTRUP Page A > (recherche de "Pourquoi ne puis-je pas affecter un vecteur à un vecteur?") p>
Vous pouvez utiliser std :: transformer code>. Il utilise toujours
pour () code> en interne, mais vous obtiendrez une implémentation de deux chaînes:
Ceci est toujours "en regardant chaque élément", le flux est juste arrangé différemment.
Il y a deux options. Le plus simple consiste à utiliser quelque chose comme } p> Je suppose un moyen de regarder une approche alternative, si vous baseez votre code autour des itérateurs uniquement, est d'envelopper l'itérateur de vecteur supprimer_copy_if code>. Je ne peux pas expliquer pourquoi ils l'appellent cela, mais il copie les éléments d'un conteneur à un autre que ne répond pas au prédicat. Voici l'idée de base (non testée):
supprimer_copy_if code> est à penser comme
copy_unless code>. p>
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;
}
// ...
};
Si vous dites que vous pouvez garantir que chaque élément est vraiment un chien, alors static_cast code> IE
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] ));
}
}
Quand vous pouvez assurer, que votre std :: vecteur
chien * code> Vous pouvez utiliser
reterpret_cast code>. p>
enfreint un aliasing strict: gist.github.com/shafik/848ae25FFFE272A58F8
Mélange de la méthodologie std :: transformation code> avec un
static_cast code> (car vous êtes certain de sa sécurité) pourrait ressembler à:
std::transform(animals.begin(), animals.end(),
std::back_insert_iterator<std::vector<Dog*>>(dogs),
[](auto ptr) { return static_cast<Dog*>(ptr); });
Duplicaté: Stackoverflow.com/questions/902667/ ...
Ce n'est pas tout à fait dupe - Notez qu'il ne copie pas de
vecteur code> à
vecteur code>, mais l'inverse!
Je suppose qu'il cherche un ajout automatique / implicite!
Merci pour les commentaires. :) Je ne savais pas comment demander cela et oui, j'ai eu du mal à savoir quoi chercher!