存储指向对象成员变量的指针

时间:2011-06-04 01:18:51

标签: c++ templates pointers

我有一个问题,一直困扰我一段时间&我还没有提出解决方案。我想创建一个存储对象和容器的容器类。根据其成员变量值之一对它们进行排序。因此,如果我有一个学生类(使用成员变量int studentID),我想根据他们的studentID值按升序将它们存储在我的Container类中。我已经将容器类设置为模板化类,因此我可以在任何项目中使用任何类。

我的Container类问题: 我无法存储对象的指针(例如Student对象)。更准确的问题是我不能将引用(?)存储到对象成员变量(例如,指向Student的studentID变量的引用/指针)。

这个问题一直困扰着我多年。任何信息或建议将受到高度赞赏。有没有办法让我的下面的Container类存储指向对象成员变量的指针?是否有不同的方法来创建可以按其成员变量排序的对象容器?

#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;   
}

2 个答案:

答案 0 :(得分:1)

如果我正确理解了这个问题,你提出的问题似乎是setstd::set可以将谓词作为第二个模板参数进行排序。 如果您准备一个比较目标成员进行排序的谓词, set中的元素将根据该成员进行排序 例如:

#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 );
}

以下是ideone的测试。

答案 1 :(得分:0)

首先,您的Collection模仿两种类型:ObjectdataType。但是,您始终只填写第一个Collection <FoodItem*> foodCol(...)。改变它:

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

接下来,

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

不应该编译。你期待Object*,而ObjectFoodItem*,所以最后你期待FoodItem**,但你传递的是一个简单的{{1} }}。更改FoodItem的定义,以便在上面的示例中只需store并传递const Object&。由于&fObject,因此您的FoodItem*会期望store,即对FoodItem* const&指针的常量引用。正是我们想要的。

就我所见,其余的看起来很好,特别是成员数据指针是正确的。但我可能会忽视某些事情,这里已经很晚了......