PDA

View Full Version : myclass::operator==() overload problem.



Nyphel
11th October 2007, 01:25
Hello :)

Qt4.3.1 Open Source Edition for Windows XP (Pro SP2), configured as "-release -shared".

I would like to overload the "==" operator for the objects of my custom class.
Let's have a look to my class :



#ifndef donnee_h
#define donnee_h

#include <QList>
#include <QString>
#include <QStringList>

class donnee
{

public:
donnee();

bool operator==(const donnee&) const;

QString nom_donnee; // Nom du répertoire ou du film concerné par la donnée
QString access_donnee; // Chemin d'accès au répertoire ou du film concerné par la donnée
QString type_donnee; // "Film" ou "Répertoire"

QStringList *liste_noms_des_films; // Si la donnée est un répertoire
QStringList *liste_acces_des_films; // Si la donnée est un répertoire

void trier_listes_des_films();

private:

};

#endif




#include <iostream>
using namespace std;

#include "donnee.h"

donnee::donnee()
{
nom_donnee = "";
access_donnee = "";
type_donnee = "";

liste_noms_des_films = new QStringList();
liste_acces_des_films = new QStringList();
}

bool donnee::operator==(const donnee &a) const
{
cout << "OPERATOR: " << a.nom_donnee.toStdString() << "\t" << nom_donnee.toStdString() << endl;
if (a.nom_donnee != nom_donnee) return 0;
if (a.access_donnee != access_donnee) return 0;
if (a.type_donnee != type_donnee) return 0;
if (a.liste_noms_des_films != liste_noms_des_films) return 0;
if (a.liste_acces_des_films != liste_acces_des_films) return 0;
return 1;
}

void donnee::trier_listes_des_films()
{
QStringList list_temp_films;
QStringList list_temp_access;
QString current_name = "";
QString smallest_name = "";
int indice_smallest_name;

// Remplissage de listes temporaires et triées
int NB_tours = liste_noms_des_films->size();
for (int i = 0; i < NB_tours; ++i)
{
smallest_name = liste_noms_des_films->at(0);
indice_smallest_name = 0;

for (int j = 0; j < liste_noms_des_films->size(); ++j)
{
current_name = liste_noms_des_films->at(j);

if(QString::compare(current_name, smallest_name, Qt::CaseInsensitive) < 0)
{
smallest_name = current_name;
indice_smallest_name = j;
}
}
list_temp_films.append(liste_noms_des_films->takeAt(indice_smallest_name));
list_temp_access.append(liste_acces_des_films->takeAt(indice_smallest_name));
}

// Mises à jour des listes, à partir des listes temporaires
liste_noms_des_films->clear();
for (int k = 0; k < list_temp_films.size(); ++k)
{
liste_noms_des_films->append(list_temp_films.at(k));
}

liste_acces_des_films->clear();
for (int l = 0; l < list_temp_access.size(); ++l)
{
liste_acces_des_films->append(list_temp_access.at(l));
}

}


This is a very simple class managing QStrings and QLists of QStrings.
I've reimplemented the "==" operator.

The class is correctly built, and I get no errors or warnings.
So I test my new "==" operator with the 2 following examples :



donnee * data_1 = new donnee();
data_1->nom_donnee = "nom data 1";
data_1->access_donnee = "access data 1";
data_1->type_donnee = "type data 1";

donnee * data_2 = new donnee();
data_2->nom_donnee = "nom data 1";
data_2->access_donnee = "access data 1";
data_2->type_donnee = "type data 1";

if (data_1 == data_2) {cout << "yes" << endl;}
else {cout << "no" << endl;}

This should display "yes", but it displays "no".




donnee * data_1 = new donnee();
data_1->nom_donnee = "nom data 1";
data_1->access_donnee = "access data 1";
data_1->type_donnee = "type data 1";

donnee * data_2 = new donnee();
data_2->nom_donnee = "nom data 2";
data_2->access_donnee = "access data 2";
data_2->type_donnee = "type data 2";

if (data_1 == data_2) {cout << "yes" << endl;}
else {cout << "no" << endl;}

This should display "no", and it displays "no".


So my first problem is that my new "==" operator returns always "false".

Another funny thing is that my new "==" operator should display a message on the cout channel each time it is invocated... But this message is never displayed, like if my new operator wasn't used. And you know what ? If I comment my new operator from donnee.h and donnee.cpp, my application is correctly build and executed, without errors or warnings... :eek:

I think I missed something, could you help me please ?
This is my first operator overload :s

jacek
11th October 2007, 01:43
You have defined == operator for donnee class, but you're trying to compare pointers.

It should be:
if( *data_1 == *data_2 ) ...

Nyphel
11th October 2007, 02:06
Ooooh yes...
Thanks Jacek :o

Nyphel
11th October 2007, 02:30
I've adjusted my operator, in order to correct the error.


bool donnee::operator==(const donnee &a) const
{
cout << "OPERATOR: " << a.nom_donnee.toStdString() << "\t" << nom_donnee.toStdString() << endl;
if (a.nom_donnee != nom_donnee) return false;
if (a.access_donnee != access_donnee) return false;
if (a.type_donnee != type_donnee) return false;
if (*a.liste_noms_des_films != *liste_noms_des_films) return false;
if (*a.liste_acces_des_films != *liste_acces_des_films) return false;
return true;
}


Now that the tests are passed, I want to really use this operator :).

I've got a QList (named "liste_donnees") filled with objects of my donnee class.
I suppose that my QList may contains 2 times the same object, and I would like to clear it in order not to have more than 1 time the same object before displaying its content on my interface.

So I loop into my Qlist, from start index to end index, and I copy my objects in a temporary QList only if the current object isn't already in this temporary QList. This is the reason why I overloaded my "==" operator. (The "contains()" method for QList requiered me to do it...)



QList<donnee *> liste_donnees_temp;

for (int i = 0; i < liste_donnees.size(); ++i)
{
if (liste_donnees_temp.contains(liste_donnees.at(i)) == false)
{
liste_donnees_temp.append(liste_donnees.at(i));
}
}


The problem is the same as in my previous post : my operator isn't used.
The reason seems to be that the same as previously. So I should modify my code like it :



QList<donnee *> liste_donnees_temp;

for (int i = 0; i < liste_donnees.size(); ++i)
{
if (liste_donnees_temp.contains(*liste_donnees.at(i)) == false)
{
liste_donnees_temp.append(liste_donnees.at(i));
}
}


But when I do a such modification, the compilator returns me an error :
[no matching function for call 'QList<donnee *>::contains(donnee&)']

Is there a solution ?
Must I search in my "liste_donnees_temp" manually, with a loop for example ?

Thanks for your help !

jacek
11th October 2007, 23:29
if (liste_donnees_temp.contains(*liste_donnees.at(i)) == false)
Unfortunately, you can't do that. QList<donnee *> is a list of pointers and you can only check whether it contains a given pointer. In Qt 3 there were special collections for storing pointers, but now they're gone.

It looks like you will have to simply traverse the list and check each item yourself. Something like:
template< class T >
bool contains( QList< T * > list, T * item )
{
foreach( T * i, list ) {
if( *i == *item ) {
return true;
}
}
return false;
}
(untested).