Вектор найти с указателями пользовательского класса - PullRequest
2 голосов
/ 23 мая 2011

Я пытаюсь понять операторы, которые нужно перегрузить при работе с пользовательскими классами в STL (SCL).

Может кто-нибудь сказать, что я делаю не так?

class myClass
{
public:
    int data;
    myClass()
    {
        data =0;
        cout<<"Default const "<<endl;
    }

    myClass(int x)
    {
        data = x;
        cout<<"Int constructor"<<endl;
    }

    myClass(const myClass &m)
    {
        cout<<"Copy constructor"<<endl;
    }

    bool operator == (const myClass &temp)
    {
        cout<<"Operator called &";
        return data == temp.data;
    }

    bool operator == (const myClass *temp)
    {
        cout<<"Operator called *";
        return data == temp->data;
    }
};

int main ()
{
    /*
    vector<int> myvector;
    myvector.push_back(10);
    myvector.push_back(20);
    myvector.push_back(30);

    cout << "myvector contains:";
    for_each (myvector.begin(), myvector.end(), meObj);
    */

    vector<myClass*> myVec;
    myClass temp;
    myVec.push_back(&temp);
    myClass temp2(19);
    myVec.push_back(&temp2);
    myClass temp3(19);

    vector<myClass*>::iterator it = find(myVec.begin(),myVec.end(),&temp2); //works
    if(it!=myVec.end())
    {
        cout<<"Value is "<<(*it)->data;
    }

    vector<myClass*>::iterator dit = find(myVec.begin(),myVec.end(),&temp3); //fails
    if(dit!=myVec.end())
    {
        cout<<"Value is "<<(*dit)->data;
    } 

    cout << endl;

    return 0;
}

Пожалуйста, исправьте меня, если я ошибаюсь, но первая находка работает так же, как и сравнение адресов.Что мне нужно перегрузить, чтобы вышеперечисленное сработало?

Имеют ли смысл обе подписи?

bool operator == (const myClass &temp); // seen in many places
bool operator == (const myClass *temp); // what if two pointer types of same object are being compared?

Ура!

Ответы [ 3 ]

3 голосов
/ 23 мая 2011

Операторские перегрузки должны иметь хотя бы один определенный пользователем тип. Таким образом, вы не можете перегрузить operator== для двух указателей, например.

Ваш myClass::operator==(const myClass *temp) действителен в том смысле, что он компилируется, но имеет очень небольшой смысловой смысл и не рекомендуется (есть очень мало ситуаций, в которых вы хотите сделать T x; T *y; ... (x == y)).

Для вашей ситуации, когда у вас есть вектор указателей, вы можете рассмотреть std::find_if, который принимает предикат . Что-то вроде:

class CompareByPointer
{
public:
    explicit CompareByPointer(const myClass &p) : p(p) {}
    bool operator() (const myClass &rhs) const { return p->data == rhs->data; }
private:
    const myClass &p;
};

...

find_if(myVec.begin(), myVec.end(), CompareByPointer(&temp2));

[Как примечание, вы должны, как правило, определять функции-члены const, где это возможно. Таким образом, перегрузки вашего оператора должны быть const.]

1 голос
/ 23 мая 2011

В примере кода вы не вставили &temp3 в myVec.Так что имеет смысл для второго std::find потерпеть неудачу.

0 голосов
/ 23 мая 2011

Что вы подразумеваете под «работой» в данном случае? Как правило, когда вы храните указатели, это происходит потому, что объекты действительно имеют идентичность, и сравнение адресов является правильным решением. В противном случае вам, вероятно, следует хранить значения (хотя есть исключения). В любом случае, вы всегда можете использовать find_if и любые критерии сравнения. Для всего, кроме самых простых типов, я все равно использую find_if чаще, чем find; обычно вы ищете не равенство, а какой-то конкретный тип соответствия. Вот, например, вы, скорее всего, захотите что-то вроде:

std::vector<MyClass>::iterator it = std::find_if( myVect.begin(), myVect.end(),
                                                  boost::bind(&MyClass::id, _1, 19) );

(Предположим, что data здесь является своего рода идентификатором, и что вы предоставили функцию-член myClass::id() для ее чтения.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...