2011-06-04 3 views
2

J'ai un problème qui m'ennuie depuis un moment & Je n'ai pas encore trouvé de solution. Je voudrais créer une classe de conteneur qui stocke les objets & les trie en fonction d'une de leurs valeurs de variable membre. Donc, si j'ai une classe d'étudiants (avec la variable membre int studentID), je veux les stocker dans ma classe Container en fonction de leur valeur ID étudiant dans l'ordre croissant. J'ai fait de la classe conteneur une classe modélisée que je peux utiliser pour n'importe quelle classe dans n'importe lequel de mes projets.Stocker un pointeur sur une variable membre d'objets

Mon problème avec ma classe Container:Je ne peux pas stocker de pointeurs d'objets (par exemple des objets Etudiants). Le problème est plus précisément que je ne peux pas stocker une référence (?) À une variable membre d'objets (par exemple une référence/pointeur vers une variable studentID de Student).

Ce problème a été agaçant moi pour les âges & toute information ou conseil serait très appréciée. Existe-t-il un moyen de rendre mes pointeurs de magasin de classe Container ci-dessous pour les variables de membre d'objets? Existe-t-il une manière différente de créer un conteneur d'objets pouvant être triés par leurs variables membres?

#include <iostream> 

using namespace std; 

template <typename Object, typename dataType> 
class Collection 
{ 
    public: 

     Collection(dataType Object::*nMemberVariable) 
     { 
      memberVariable = nMemberVariable; 
     } 

     bool store(Object* o) 
     { 
       // check that o is not a NULL pointer & not already present in maps 
       if (o==NULL || instanceVarMap.find(o->*memberVariable) != instanceVarMap.end()) 
       { 
        return false; 
       } 

       instanceVarMap.insert(o->*memberVariable, o); 
       return true; 
     } 

    private: 
     dataType Object::* memberVariable; 
     std::map <dataType, Object*>  instanceVarMap; 
}; 


struct FoodItem 
{ 
    unsigned int ID; 
    string name; 
    double price; 
}; 


int main() 
{ 

    // I am attempting to store a pointer to an objects member variable 
    // this is so I can create a custom container class(like a map or vector) that 
    // sorts its contents (which are FoodItem objects) according to their member variable values 
    // so a container could sort all its elements according to a FoodItems ID value or name value 

    Collection <FoodItem*> foodCol(&FoodItem::name); 

    string nNames[]   = {"a", "b", "c", "d"}; 
    double nPrices[]   = {1.1, 2.2, 3.3, 4.4}; 

    for (int i=0; i<4; i++) 
    { 
     FoodItem *f = new FoodItem() { i, nNames[i], nPrices[i] }; 
     foodCol.store(f); 
    } 

    // Note storing an ACTUAL object is possible with this class 
    Collection <FoodItem*> foodCol(&FoodItem::name); 
    FoodItem f(1, "a", 4); 
    foodCol.store(f); 

    system("PAUSE"); 
    return 0; 
} 

Répondre

0

D'abord, votre Collection est basé sur un modèle sur deux types: Object et dataType. Cependant, vous devez toujours remplir le premier comme Collection <FoodItem*> foodCol(...). Changer cela aussi:

Collection <FoodItem*,string> foodCol(&FoodItem::name); 

Ensuite,

FoodItem f(1, "a", 4); 
foodCol.store(f); 

ne devrait pas compiler. Vous attendez un Object*, alors que Object est un FoodItem*, donc à la fin vous attendez un FoodItem**, mais ce que vous passez est un simple FoodItem. Changez la définition de store donc il suffit d'un const Object& et passez le &f dans l'exemple ci-dessus. Puisque Object est FoodItem*, votre store s'attendra à un FoodItem* const&, c'est-à-dire une référence constante à un pointeur FoodItem*. Exactement ce que nous voulons.

Le reste semble bien aussi loin que je peux voir, en particulier le pointeur de données membre est correct. Mais je pourrais être en train de négliger quelque chose, il est très tard ici ...

1

Si je comprends bien la question, ce que vous avez demandé semble set. std::set peut prendre un prédicat pour le tri en tant que deuxième argument de modèle. Si vous préparez un prédicat qui compare le membre cible au tri, les éléments du set seront triés en fonction de ce membre.
Par exemple:

#include <set> 

struct FoodItem { 
    unsigned int ID; 
    double price; 
}; 

template< class C, class T, T C::* M > 
struct member_comparator { // predicate 
    bool operator()(C const* x, C const* y) const { return x->*M < y->*M; } 
}; 

int main() { 
    FoodItem a = { 1, 2.5 }, b = { 2, 1.5 }; 
    // a set sorted by ID 
    std::set< FoodItem* 
      , member_comparator< FoodItem, unsigned, &FoodItem::ID > > s_ID; 
    s_ID.insert(&a); 
    s_ID.insert(&b); 
    // a set sorted by price 
    std::set< FoodItem* 
      , member_comparator< FoodItem, double, &FoodItem::price > > s_price; 
    s_price.insert(&a); 
    s_price.insert(&b); 
} 

Voici un test sur ideone.

Questions connexes