Проблема перегрузки оператора <в C ++ - PullRequest
3 голосов
/ 12 октября 2009

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

Чтобы сделать это, я понимаю, что мне нужно перегрузить оператор "<", но после попытки (и сбоя) несколькими методами, предложенными в сети, у меня заканчиваются идеи. </p>

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

В 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();
}

где "Name ()" - это константа, которая возвращает строку.

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

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

Ответы [ 4 ]

9 голосов
/ 12 октября 2009

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

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

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

6 голосов
/ 12 октября 2009

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

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

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

Обратите внимание на конечный констант, указывающий, что внутри оператора <, * это константа. </p>

РЕДАКТИРОВАТЬ Я не могу удалить этот ответ, потому что он был принят, но я бы сделал, если бы мог. Я также не могу заменить его на правильный. См. Комментарий Дрю Дорманна ниже и ответ Росса Смита .

2 голосов
/ 12 октября 2009

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

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

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

1 голос
/ 12 октября 2009

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

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

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

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