Const функция в контейнерах STL - PullRequest
0 голосов
/ 10 декабря 2011

У меня проблема с использованием контейнеров STL в c ++

функция 1;

void addStudent(const Student &s){                       
    set<GradeColumn>::iterator itr;

    for(itr = gradeColumns.begin(); itr != gradeColumns.end(); itr++){
        itr->addStudent(s, DID_NOT_COMPLETE);
    }
}

функция 2:

void addStudent(const Student &s,  int grade) const {
    column.insert(pair<Student, int>(s, grade));
}

Хорошо, поэтому в функции 1 я использую addStudent, но компилятор выдает мне ошибку, если я не объявляю addStudent в качестве const-функции (ошибка «Объект имеет спецификаторы типов, которые не совместимы с функцией-членом»).

Но если я объявлю addStudent в качестве const-функции, то column.insert (...) выдаст мне следующую ошибку: «Ни один экземпляр перегруженной функции не соответствует списку аргументов, а у объекта 9 объект имеет квалификаторы типов, которые препятствуют совпадению )».

Есть ли способ это исправить? Я что-то упустил?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 10 декабря 2011

Ключи std::set всегда постоянны.Это требование к контейнеру, так как элементы упорядочены по значению ключа, и если ключи были изменяемыми, контейнер не может гарантировать, что его инварианты поддерживаются.

Если ваш реляционный оператор на GradeColumn имеет значениенезависимо от того, к чему вам нужно получить доступ в функции-члене insert(), вы можете объявить эти объекты-члены mutable, чтобы вы могли изменять их, даже если сам ключевой объект является постоянным.

1 голос
/ 10 декабря 2011

Ответ зависит от вашего ответа на мой комментарий.Если ваш ответ:

" да, addStudent можно изменить GradeColumn заказ "

Ответ: Дизайн ассоциативных контейнеров спас вас как объяснено в других ответах.

" нет, addStudent не может измениться GradeColumn заказ "

Ответ: Дизайн ассоциативных контейнеров снова поражает.

Исправление (эскиз):

class GradeColumnElement {
    mutable GradeColumn col;

    friend bool operator<(const GradeColumnElement& left, const GradeColumnElement& right) {
        return left.col < right.col;
    }

public:
    GradeColumnElement (const GradeColumn& col) : col(col) {
    }

    // const interface: 
    // modifications of GradeColumn that do NOT affect ordering
    void addStudent(const Student &s, int grade) const {
        col.addStudent (s, grade);
    }
};

, затем вы используете set<GradeColumnElement> вместо set<GradeColumn>.

1 голос
/ 10 декабря 2011

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

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

...