2015-08-05 6 views
5

Я пытался понять, когда я пишу функцию в C++ с постоянным аргументом и переменную-указатель внутри этого объекта, чем флаг const не защищает базовую память от изменений. Например, это совершенно законно, чтобы сделать следующее в operator=() функции класса под названием X:Почему в C++ разрешено изменять переменную-переменную-константу объекта-объекта извне?

class X 
{ 
public: 
    X& operator=(const X& other) 
    { 
     this->data = other.data; //(*) 
     return *this; 
    } 

private: 
    int* data; 
}; 

(*): Это то же самое, как:

int* some_pointer; 
int* const other_pointer = some_pointer; 
int* class_pointer = other_pointer; 

Но не то же самое как:

const int* other_pointer; 
int* class_pointer = other_pointer; 

Какой бы генерировать следующую ошибку:

error: invalid conversion from 'const int*' to 'int*' [-fpermissive] 
int* class_pointer = other_pointer; 
        ^

Я понимаю, почему other.x в настоящее время отливают в int* const, но я не понимаю, почему он не отлит в const* int в то же время (что является const int* const). Когда я пишу функцию с аргументом const, моя логика предполагает, что что-либо внутри этого аргумента должно наследовать константу, поскольку это должно быть целью const, чтобы защитить базовые данные от модификации.

Когда член указатель осуществляется доступ извне версии класса const Я думаю, это должно быть разумно ожидать, что const ключевого слова объекта должно защищать что-либо (даже память), которая выходит из класса от модификации. Аргумент против этого заключается в том, что внешняя память не принадлежит объекту, поэтому не следует также защищать ее. Моя перспектива заключается в том, что в этом случае (из любых других случаев, когда к нему обращаются куда-либо еще с любыми правами доступа) мы берем что-то из объекта const. Другими словами, это дает видимость чему-то вне себя. Итак, в чем причина отсутствия видимости const? Это не изменит права доступа к памяти в любом другом месте кода!

+2

Я не совсем уверен, что вы просите здесь. Уточнить? – juanchopanza

+1

Я спрашиваю, почему other.data (в функции X :: operator =()) не выполняется для const int * const, а не только для int * const и что было конструктивным решением для этого в C++. – Kristof01

+0

Потому что это не имеет никакого смысла. – juanchopanza

ответ

0
int* const other_pointer 
declare other_pointer as const pointer to int 

в противоположность:

const int* other_pointer 
declare other_pointer as pointer to const int 

Любезность http://cdecl.org/

Обратите внимание на разницу в размещении Уст.

+1

OP, похоже, знает об этом. – Quentin

4

"When I write a function with a const argument my logic suggests anything inside that argument should inherit the constness because that should be the purpose of const, to protect the underlying data against modification."

Вы совершенно правы об этом, однако указатель хранится внутри X -объекта точек вне объекта. Внешняя сторона не зависит от константы X, только данные, хранящиеся внутри X.

+0

Я полностью согласен, но это должно быть обязанностью const X обеспечивать постоянную видимость этой «внешней» памяти, если C++ действительно будет рассматривать X и все в X как что-то, что не поддается изменению. Это не повлияет на внешнюю память! – Kristof01

+1

Я предполагаю, что доходит до того, что «внешние» данные * принадлежат * текущему классу. Если да, то это вовсе не внешние данные. Возможно, исходный вопрос OP «почему не являются указателями-членами, которые, как предполагается, являются указателями на * принадлежащие * данным, и, следовательно,' const'-propogating? » –

+0

... (продолжение) В C++ у нас уже есть ключевое слово 'mutable', чтобы разрешить использование для мутации членов в методах' const' - намерение состоит в том, что эти изменения не изменят «логическую» конструкцию методы. Таким образом, возможно, указатели должны были быть 'const'-propogating по умолчанию, но с' mutable', чтобы изменить это там, где это необходимо (включая не принадлежащие). * (Конечно, нам уже около 30 лет, чтобы сделать это!) * –

0

Вы не меняете значение other.data, так что нет const нарушения. Вы, конечно же, можете изменить объект, на который указывает other.data, но это не входит в компетенцию компилятора для обеспечения соответствия const-correctness.

1

Почему вы думаете, что, поскольку указатель постоянный, то, что указано, должно быть постоянным? Это не обязательно.

Иногда вам нужен указатель, который всегда должен указывать на конкретное место, но через которое вы можете изменить указанное место. Нет ничего о class X, который предполагает, что вы не сможете изменить память data пунктов.

Что еще более важно, вы неправильно думаете о ключевом слове const. Учитывая

X& operator=(const X& other) 

все, что вы делаете, это говорит компилятору, что вы не собираетесь менять other внутри operator=() и попросить компилятор, чтобы помешать вам делать это в случае, если вы забыли. Ни больше ни меньше. Он ничего не говорит о constness of other вне operator=(), ни о константе чего-либо любого указателя внутри other указывает на.