我有一个问题,一直困扰我一段时间&我还没有提出解决方案。我想创建一个存储对象和容器的容器类。根据其成员变量值之一对它们进行排序。因此,如果我有一个学生类(使用成员变量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;
}
答案 0 :(得分:1)
如果我正确理解了这个问题,你提出的问题似乎是set
。
std::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
模仿两种类型:Object
和dataType
。但是,您始终只填写第一个Collection <FoodItem*> foodCol(...)
。改变它:
Collection <FoodItem*,string> foodCol(&FoodItem::name);
接下来,
FoodItem f( 1, "a", 4 );
foodCol.store( f );
不应该编译。你期待Object*
,而Object
是FoodItem*
,所以最后你期待FoodItem**
,但你传递的是一个简单的{{1} }}。更改FoodItem
的定义,以便在上面的示例中只需store
并传递const Object&
。由于&f
为Object
,因此您的FoodItem*
会期望store
,即对FoodItem* const&
指针的常量引用。正是我们想要的。
就我所见,其余的看起来很好,特别是成员数据指针是正确的。但我可能会忽视某些事情,这里已经很晚了......