PDA

View Full Version : QList contains problem with custom objects



saravanadel
25th January 2012, 07:41
Hi,

I have Qlist with Customclass objects. When I check the QList with 'contains' method using a Custom class reference it returns false.I have also overridden the 'operator=='.

I know that I am using pointers to compare rather than value.

What should I do to achieve this.


QList <CustomClass *>list;
CustomClass *c1=new CustomClass();
c1.name= "john";
list.append(c2);
CustomClass *c2=new CustomClass();
c2.name= "john";

qDebug()<<list.contains(c2); //false

class CustomClass : public QObject
{
QString name;
bool operator==(const CustomClass& other)const
{
if(this->name==(other.name))
{
return true;
}
return false;
}
}


One more thing.
I cannot and don't want to have QList <CustomClass>list, because QObject does not allow it (unless I override constructors).

FelixB
25th January 2012, 08:24
The List does not contain c2 because c2 does not point to the same object as c1. Create a free function



bool operator==(const CustomClass* lhs, const CustomClass* rhs)
{
return *lhs == *rhs;
}


Are you sure that QList uses operator==? Maybe you need to define operator<...

Felix

saravanadel
25th January 2012, 09:33
The List does not contain c2 because c2 does not point to the same object as c1. Create a free function



bool operator==(const CustomClass* lhs, const CustomClass* rhs)
{
return *lhs == *rhs;
}


Are you sure that QList uses operator==? Maybe you need to define operator<...

Felix

When I declare this it says , 'bool operator== (const CustomClass* lhs, const CustomClass* rhs) must have an argument of class or enumerated type'

wysota
25th January 2012, 10:02
This won't work. Since c1 and c2 are different objects, comparing pointers will compare their addresses which are different. Your operator will not be used at all.

You need to declare the operator for comparing pointers (as already advised) and you need to do that in a place where your class is visible (like right after the semicolon ending your class definition).

saravanadel
25th January 2012, 10:13
When I declare this it says , 'bool operator== (const CustomClass* lhs, const CustomClass* rhs) must have an argument of class or enumerated type'

How I declared,


//CustomClass.h
class CustomClass
{
};
bool operator==(const CustomClass* lhs, const CustomClass* rhs)
{
return *lhs == *rhs;
}
//End of header

wysota
25th January 2012, 11:32
In that case you can't override the operator for comparing pointers. The only thing you can do is to check whether QList accepts an additional parameter acting as a comparator for items it holds.

Edit: no, it doesn't.

stampede
25th January 2012, 11:35
When I declare this it says (...)
I don't think you can do that in C++. Pointers are built-in types, they have standard behavior for operations like <,>,== etc. It's like you want to overload operator == for integers, compiler should not allow you to do that.
Why do you want to store pointers in the QList, can't you just use QList<CustomClass> ?

@down:
right, I missed that, because of the code from post #5.

wysota
25th January 2012, 11:51
He can't because the class inherits QObject. The real question is whether it really has to inherit QObject.

saravanadel
25th January 2012, 12:37
Does this boil down to a limitation. What I mean is take language objective-c, java, python for example. Searching a list should be easy.

Here I want to use the Qt QObject model, but I cant use pointers in QList (becoz they cant search with pointers).

wysota
25th January 2012, 12:43
Searching a list is easy. But if the list contains apples and you try to search it for oranges, you will find nothing of interest. All those languages you mentioned have no notion of pointers, by the way.

stampede
25th January 2012, 12:46
I agree with wysota - searching a list works perfectly fine as long as you know what you are doing.

Here I want to use the Qt QObject model, but I cant use pointers in QList (becoz they cant search with pointers).
Probably you can get away with simple wrapper class, but this is not very elegant solution:


#include <QApplication>
#include <QDebug>
#include <QObject>

class CustomClass : public QObject
{
public:
QString name;
bool operator==(const CustomClass& other)const
{
if(this->name==(other.name))
{
return true;
}
return false;
}
};

class CustomClassPtr{
public:
CustomClassPtr(CustomClass * ptr) : _ptr(ptr){
}
CustomClass * _ptr;
};

bool operator==(const CustomClassPtr& p1, const CustomClassPtr& p2){
return *p1._ptr == *p2._ptr;
}

int main(int argc, char **argv)
{
QList <CustomClassPtr>list;
CustomClass *c1=new CustomClass();
c1->name= "john";
list.append(c1);
CustomClass *c2=new CustomClass();
c2->name= "john";

qDebug()<<list.contains(c2); //true

return 0;
}

I skipped the pointer checks etc. just to present the idea.

wysota
25th January 2012, 14:23
One can also use QSharedPointer and/or QWeakPointer or even QPointer (alas it's deprecated).

By the way, searching the list this way (I mean using QList::contains) is not a good idea. The complexity is then O(n). Either presort the list and use qBinaryFind (using a dedicated LessThan implementation so that you don't have to use any pointer wrappers) or use QHash and search by key (you don't need any extra treatment then). You'll get O(logn) then.