Не беспокойтесь о том, что пользователи делают const_casts, чтобы сломать ваши инварианты. Если они действительно хотят взломать ваш код, они могут без предоставления вам доступа к вашим внутренним атрибутам. Возвращая постоянную ссылку, обычный пользователь не будет ошибочно изменять ваши данные.
Инкапсуляция предотвращает ошибки, а не шпионаж Вредоносный кодер может все равно сломать его, если он действительно заботится и знает среду (компилятор). Константность теряется в процессе компиляции (во всех известных мне компиляторах). Как только модуль компиляции преобразуется в двоичные объекты, эти объекты не знают о постоянстве, и его можно использовать для получения преимущества.
// a.h
class A
{
public:
A( int a ) : data_( a ) {}
int get() const { return data_; }
private:
int data_;
};
// malicious.h
class A;
void change( A& a, int new_value );
// malicious.cpp
// does not include a.h, but redefines an almost exact copy of it
class A {
public:
A( int a ) : data_( a ) {}
int get() const { return data_; }
int data_; // private removed
};
void change( A& a, int new_value )
{
a.data_ = new_value;
}
// main.cpp
#include "a.h"
#include "malicious.h"
int main()
{
A a(0);
change( a, 10 );
std::cout << a.get() << std::endl; // 10
}
Хотя приведенный выше код неверен (одно правило определения нарушено, существует два определения для класса A), факт заключается в том, что в большинстве компиляторов определение A и вредоносного A совместимы в двоичном формате. Код будет компилироваться и связываться, и в результате внешний код будет иметь доступ к вашим личным атрибутам.
Теперь, когда вы знаете об этом, не делайте этого . Позже это будет боль обслуживания в ***. Это стоило Microsoft немалых денег за обеспечение обратной совместимости с программным обеспечением, в котором использовались закрытые части возвращаемых объектов API (новые версии API, использующие тот же общедоступный интерфейс, но изменившие внутренние компоненты, могут нарушить работу некоторого стороннего кода приложения). С некоторым широко доступным программным обеспечением поставщик (в данном случае Microsoft) будет испытывать трудности с обеспечением обратной совместимости, но с менее известными приложениями этого не произойдет, и внезапно ваше ранее запущенное приложение выйдет из строя во всех отношениях.