2009-10-12 3 views
3

У меня есть вектор объектов Student, который я хочу, чтобы отсортировать с помощью #include <algorithm> и sort(list.begin(), list.end());Проблема перегрузки оператора <в C++

Для того, чтобы сделать это, я понимаю, что мне нужно перегрузить «<» оператора, но после того, как пытаясь (и неудачно) с несколькими методами, предлагаемыми в Интернете, у меня заканчиваются идеи.

Вот моя последняя попытка:

В Student.h ...

... 
using namespace std; 
class Student 
{ 
    friend bool operator <(const Student& first, const Student& second); 
    public: 
    ... 
    private: 
    ... 
}; 

И в Student.cpp ...

... 
#include "Student.h" 
using namespace std; 
... 
bool operator <(const Student& first, const Student& second) 
{ 
    return first.Name() < second.Name(); 
} 

где "Имя()" является постоянная функция, которая возвращает строку.

Программа компилируется и работает, но мой оператор-функция не вызывается во время сортировки и когда я пытался сравнивать два Student объекты, такие как s1 < s2 я получил «Ошибка: перегруженный оператор не найден»

Как я могу правильно перегрузочную этот оператор, чтобы мой сорт работал, как я предполагаю?

ответ

6

Я бы не стал использовать друга здесь, и я не уверен, что он работает вообще. То, что я хотел бы использовать это ...

class Student 
{ 
    public: 
    bool operator< (const Student& second) const; 
}; 

bool Student::operator< (const Student& second) const 
{ 
    return (Name() < second.Name()); 
} 

Примечание тянущаяся Const, указывая, что внутри оператора <, * это константа.

EDIT Я не могу удалить этот ответ, потому что он был принят, но если бы я мог. Я также не могу заменить его на правильный. См. Комментарий Дрю Дорманна ниже, и Ross Smiths answer.

+0

Я думаю, что, наконец, я решил ответить на этот вопрос, потому что именно тот, который наиболее непосредственно дал мне определение большей проблемы, которую я имел с моими указателями. –

+4

Этот подход часто избегается, потому что, если типы конвертируются в Student, код преобразует правый тип, но не левый тип. Функция друга будет вести себя последовательно для обеих сторон. –

1

Ну, вы могли бы сделать это в качестве внутреннего оператора:

class Student 
{ 
    public: 
    bool operator <(const Student& second) const; 
    ... 
    private: 
    ... 
}; 

С реализацией сравнения «это» на второй. Вопрос, на мой взгляд, заключается в том, что метод «Имя» привнес в созвездие? Потому что, если это не так, вы не можете написать метод const, который его использует.

+0

Похоже, что оба параметра «первый» и «второй» в версии для друзей были const. – Steve314

9

Вы не сказали, какой компилятор вы использовали, но я подозреваю, что вы используете довольно недавний, который реализует правило «друг не является объявлением». Оператор friend внутри класса не служит объявлением функции; другие модули, которые включают Student.h, не видят объявления функции. Это видно только внутри файла Student.cpp. (Старые компиляторы не имеют этого правила и обрабатывают объявление друга как объявление функции.)

Функция не обязательно должна быть другом, поскольку она не использует каких-либо частных членов класса Student (Я предполагаю, что имя() открыто). Переместите объявление функции вне класса и замените «friend» на «extern», и он должен работать.

Можно сделать оператор функцией члена, так как некоторые плакаты, предложенные выше, но это необязательно. Выполнение функций-членов операторов сравнения, как правило, неодобрительно, потому что это означает, что два аргумента не обрабатываются симметрично (один из них является невидимым «этим» аргументом, другой - нормальным аргументом функции), что может привести к неожиданным результатам в некоторых случаях (например, к аргументам могут применяться разные преобразования типов).

+0

Нужно ли отмечать выражение функции extern? Я делал это только с переменными, объявленными в файлах заголовков. –

+0

Трудно было решить один ответ на этот вопрос. Мои первоначальные попытки были определены в классе, и я попробовал версию «друга» из отчаяния после прочтения чьей-то претензии, что «сортировка» не будет выполняться, если вы этого не сделаете. Оказалось, что у меня на самом деле была проблема с указателем. –

+0

Правда, на самом деле это не обязательно; функции внешних классов имеют внешнюю связь по умолчанию. У меня есть привычка вводить его, чтобы указать читателю, что функция определена в другом исходном файле (в отличие от прямого объявления функции, определенной в другом месте в том же файле). –

2

Кстати, с помощью функции это просто я лично просто сделать это, если стиль руководства не запрещает определение функций внутри определения класса:

class Student 
{ 
    friend bool operator <(const Student& first, const Student& second) 
    { 
     return first.Name() < second.Name(); 
    } 
    ... 
}; 

Эта форма «друга» декларация позволяет define a не является членомoperator< внутри кузова класса. Это все еще друг, поэтому Name() может быть приватным, если это необходимо.

Смежные вопросы