2012-01-13 6 views
0

j'ai la configuration suivanteObtenir des vecteurs des membres de vecteurs d'objets

class obj { 
    public: 
    int a(); 
    int b(); 
    int c(); 
    int d(); 
}; 

std::vector<obj> obj_vector; 
//Fill obj_vector 

et je voudrais accéder aux méthodes (ce qui est une interface qui attend des vecteurs de ints, individuellement). Je pensais d'abord que l'extension du vecteur était la meilleure approche, mais ont été mis en garde contre elle.

J'ai mis

get_a_vec(vector<obj>); 

etc, mais c'est un peu maladroit. Y a-t-il de bonnes alternatives?

Merci d'avance!

+0

Les vecteurs ne sont pas énormes, donc la performance n'est pas vraiment un problème, dans le cas où cela influence la solution optimale. – invisiblerhino

+0

Êtes-vous en train de dire que votre consommateur attend un «vecteur » avec quatre éléments, ou un «vecteur »? –

+0

Désolé, le consommateur a besoin d'un vecteur de obj.a, un vecteur de obj.b, un vecteur de obj.c, et un vecteur de obj.d. Est-ce plus clair? – invisiblerhino

Répondre

0

Ce que je compris est que vous voulez une fonction qui extrait les valeurs de a de vos obj s dans un donné vector et les met dans une autre vector, si cela est vrai, alors je suggère d'utiliser une fonction friend.

La déclaration d'une fonction amie dans la classe obj permet à cette fonction d'accéder aux private membres de données de cette classe.

class obj { 
    friend vector<int> get_a_vec(const vector<obj>&); 
    friend vector<int> get_b_vec(const vector<obj>&); 
    friend vector<int> get_c_vec(const vector<obj>&); 
    friend vector<int> get_d_vec(const vector<obj>&);  
    int a; 
    int b; 
    int c; 
    int d; 
}; 

vector<int> get_a_vec(const vector<obj>& vec) 
{ 
    vector<int> result(vec.size()); 
    for (unsigned i = 0;i<vec.size();i++) 
     result->at(i) = vec[i].a; 
    return result; 
} 
+0

pourquoi voudriez-vous allouer dynamiquement le vecteur ?? C'est une idée horrible car il faut du code utilisateur pour gérer la mémoire juste pour éviter une * copie * qui n'est probablement même pas faite (ie c'est optimisé) –

+0

Pour pouvoir le retourner, sinon tu suggères de le retourner sans avoir à le transmettre par référence? aussi le rendre en valeur est très mauvais. –

+2

Je pense que vous avez une idée fausse ici. Retourner un objet créé à l'intérieur de la fonction par valeur n'est pas forcément cher.Dans tous les compilateurs actuels que je connais, la convention d'appel pour une fonction qui retourne un objet complexe alloue l'objet dans la pile de l'appelant et passe un pointeur vers cet espace alloué. La fonction elle-même construit le nouvel objet directement à l'endroit où l'appelant l'attend et aucune copie n'est faite. En allouant dynamiquement le vecteur, vous avez ajouté des coûts (allocation supplémentaire) et de la complexité à l'appelant (besoin de gérer la mémoire) –

1

On pourrait écrire une fonction générique pour extraire tout membre de la classe à partir d'une séquence d'objets:

template <typename InIt, typename OutIt, typename Class, typename Member> 
void extract(InIt start, InIt end, OutIt out, Member Class::*member) { 
    for (; start != end; ++start, ++out) { 
     *out = (*start).*member; 
    } 
} 

// Example 
int main() 
{ 
    std::vector<obj> objs {{1,2,3,4},{5,6,7,8}}; 
    std::vector<int> ints; 

    extract(objs.begin(), objs.end(), back_inserter(ints), &obj::a); 

    std::copy(ints.begin(), ints.end(), 
       std::ostream_iterator<int>(std::cout, "\n")); 
} 
+1

ou vous pouvez écrire un foncteur et l'appliquer au vecteur avec 'std :: transform' – jalf

+0

Je pense qu'il se plaint d'avoir' a' en tant que membre 'private', est-ce que cela fonctionne même si? –

+0

Qu'est-ce que Field? La solution semble bonne, c'est ce que j'avais en tête. – invisiblerhino

2

écrire une fonction qui extrait l'élément souhaité à partir d'un seul objet.

Passez ensuite cette fonction à std::transform.

Si vous avez une fonction int get_a_member(obj&), par exemple, il suffit d'appeler

std::vector<int> avec; 
std::transform(obj_vector.begin(), obj_vector.end(), get_a_member); 

Si vous voulez une fonction plus complexe ou réutilisable, faire un foncteur à la place. Ensuite, vous pouvez lui passer des paramètres dans son constructeur (par exemple lui dire quel membre retourner).