Почему это происходит? - PullRequest
       16

Почему это происходит?

3 голосов
/ 15 октября 2011

С учетом следующего кода:

class TestA
{
    private:
        char Temp;

    public:
        char *Ptr;

        TestA(){Ptr = NULL; Temp = 'A'; Ptr = &Temp;}
        void Function(){Ptr = &Temp; Temp = 'B';}

        void operator=(const TestA &ItemCopy)
        {
            //ItemCopy.Temp = 'N'; //Not permitted
            printf("%c!\n",ItemCopy.Temp);
            Ptr = ItemCopy.Ptr; //This is okay
            *Ptr = 'M'; //This is okay, but it re-assigns ItemCopy.Temp. What?
            printf("%c!\n",ItemCopy.Temp);
        }
};

int main()
{
    TestA Temp1,Temp2;

    Temp1.Function();
    Temp2 = Temp1;
}

Производит следующее:

B
М

Несмотря на то, что ItemCopy является постоянным. Почему мне разрешено косвенно изменять его или даже брать неконстантную копию указателя?

Ответы [ 5 ]

9 голосов
/ 15 октября 2011

Поскольку ItemCopy является константой, ItemCopy.Ptr имеет эффективный тип char * const. Указатель является постоянным, но указанный элемент может быть изменен. Это означает, что назначение:

*ItemCopy.Ptr = 'M';

является значимым и разрешенным (базовый объект не является самим const), также допустимо копировать указатель и назначать через него, как вы это сделали. Прямое присвоение ItemCopy.Temp = 'M' было бы недопустимым, но это не означало, что вы не можете изменить переменную ItemCopy.Temp, если у вас есть другой не-const путь доступа, как у вас.

2 голосов
/ 15 октября 2011

Ptr указывает на ItemCopy.Ptr, что в свою очередь указывает на Temp.Поэтому, когда вы разыграете его, вы будете писать Temp.

2 голосов
/ 15 октября 2011

Псевдоним указателя. Присваивая ItemCopy::Ptr this->Ptr, вы создаете псевдоним указателя и через него присваиваете другое значение. Также помните правило 3 при написании подобных вещей.

1 голос
/ 15 октября 2011

Семантика:

    const TestA &ItemCopy

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

0 голосов
/ 15 октября 2011

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

Во время выполнения вы назначаете неконстантному ptr-адресу, на который также ссылается идентификатор const, но между ними нет соединения во время компиляции, поскольку константность применяется только к одному из способов доступа к нему. и даже тогда, только в рамках этой одной функции. Он не может обрабатывать ваш неконстантный указатель как const в некоторых случаях и неконстантный в других на основе состояния времени выполнения, что может нарушить семантику C ++ другими способами.

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