2016-05-09 3 views
1

У меня есть кусок кода, как это:Есть ли хорошее правило для использования 'const' в классах и перегрузках операторов в C++?

class EducationalCentre 
{ 
    string _centreName; 
    vector<Course> _courses; // courses offered by the Centre 
    Collection<Course*, Student*, 150> _applicants; 

public: 
    EducationalCentre(string name="<name>") 
    { 
     _centreName = name; 
    } 

    EducationalCentre(const EducationalCentre& obj) 
     :_courses(obj._courses), _applicants(obj._applicants) 
    { 
     _centreName = obj._centreName; 
    } 
}; 

Теперь, в этой части заголовка строительства _applicants(obj._applicants) копии, есть волнистый красная линия вокруг (obj, парит это что-то о типе несовместимости (const упоминается) ошибка говорит ,

Поскольку я не хочу ничего менять на этом этапе (это часть экзаменационного теста) - я хотел бы знать, почему это происходит.

Я попытался удалить const от EducationalCentre(const EducationalCentre& obj), и это действительно решает проблему, но ... Как я уже сказал, я бы предпочел узнать, что вызывает это, а не удалять его.

+0

Как выглядит конструктор копии 'Collection'? Также, если вы скомпилируете то, что является фактическим сообщением об ошибке, которое вы получаете? – NathanOliver

+3

'Collection' copy ctor, принимающий неконстантный аргумент, объяснил бы это поведение. Копировать ctor следует аргумент const. –

+3

Отойдите от «коротких красных линий». Ваш код должен передать компилятор, а не IDE! –

ответ

5

Правило для использования const является использование его всякий раз, когда вы можете :)

Конечно, как и все лучшие практики, есть исключения, но в целом вы должны всегда стремиться сделать не-статические методы const если они надевают 't мутировать состояние объекта.

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

Конструктор копирования может принимать константу или не const-ссылку в качестве аргумента, но IMO, non-const следует использовать только тогда, когда у вас нет выбора, что редко. Создание объекта на основе другого объекта не должно изменять исходный объект, поэтому его следует пометить как const.

Как я заметил в комментарии, класс, являющийся общим, не имеет ничего общего с копией ctor, принимающей const-ссылку. Действительно, если вы посмотрите на, например, std::vector вы увидите, что он имеет конструктор копирования, который принимает константу ссылки. Вероятно, некоторые из методов, которые вы используете в конструкторе копирования Collection на вашем аргументе, не являются константами, и поэтому вы не можете создать аргумент const. Решение заключается в том, чтобы сделать метод оскорбления const тоже.

Это приводит нас к важному вопросу: const ness является вирусным. Если вы помечаете метод const, любой другой метод, который он вызывает сам, должен также быть const. То же самое для методов вызова для объектов const - вы можете вызывать только вызовы методов const. Если вы не делаете этого с самого начала, вы можете оказаться в ситуации, когда создание одного метода const приводит к изменению целой цепи других методов, поэтому легче отказаться.

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

Теперь, C++ не только объектно-ориентированный язык, так что вы можете изменить состояние приложения другими способами, а также вы можете неправильно mutable и const_cast обмануть компилятор, но с использованием const помогает в написании правильного программного обеспечения и уменьшая усилия по отладке.