вопрос новичка: преобразование константного языка c ++ в неконстантное - PullRequest
39 голосов
/ 05 сентября 2011

В настоящее время я действительно раздражен ключевым словом const, так как я не совсем знаком с ним.У меня был вектор, в котором хранятся все константные указатели, такие как vector<const BoxT<T> *> *Q_exclude, и в конструкторе другого класса мне нужно, чтобы элемент в этой очереди передавался как параметр и назначал его неконстантному члену.Мой вопрос:

Как мне назначить константную переменную неконстантной переменной?Я знаю, что это не имеет смысла, потому что, в конце концов, const - это const, и его не следует менять никакими средствами.Но эта раздражающая переменная-член ДЕЙСТВИТЕЛЬНО должна быть изменена во время процесса!Я мог бы также изменить тип данных в векторе, чтобы он был неконстантным, но это было бы слишком много работы.Или кто-нибудь знает, как избежать такой ситуации?

Ответы [ 4 ]

78 голосов
/ 05 сентября 2011

Вы можете назначить объект const отличному от const объекту. Поскольку вы копируете и таким образом создаете новый объект, const ness не нарушается.

Вот так:

int main() {
   const int a = 3;
   int b = a;
}

Это отличается , если вы хотите получить указатель или ссылку на оригинал, const объект:

int main() {
   const int a = 3;
   int& b = a;       // or int* b = &a;
}

//  error: invalid initialization of reference of type 'int&' from
//         expression of type 'const int'

Вы можете использовать const_cast, чтобы взломать безопасность типов, если вам действительно нужно, но помните, что вы делаете именно это: избавление от безопасности типов. все еще не определено для изменения a до b в в приведенном ниже примере :

int main() {
   const int a = 3;
   int& b = const_cast<int&>(a);

   b = 3;
}

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

Если вы пришли к тому, что считаете необходимым для этого, я бы срочно пересмотрел ваш дизайн, потому что с ним что-то не так.

8 голосов
/ 05 сентября 2011

Изменение типа константы приведет к неопределенному поведению .

Однако, если у вас есть изначально неконстантный объект, на который указывает указатель на констант или на который ссылается ссылка на констант, вы можете использовать const_cast , чтобы избавиться от Уст-Несс.

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

4 голосов
/ 05 сентября 2011

Фактический код для удаления константы вашего указателя будет:

BoxT<T> * nonConstObj = const_cast<BoxT<T> *>(constObj);

Но обратите внимание, что это действительно обман.Лучшим решением будет либо выяснить, почему вы хотите изменить объект const, и перепроектировать свой код, чтобы вам не пришлось .... или удалить объявление const из вашего вектора, если окажется, что вы недействительно хочу, чтобы эти элементы были доступны только для чтения.

1 голос
/ 11 июля 2018
void SomeClass::changeASettingAndCallAFunction() const {
    someSetting = 0; //Can't do this
    someFunctionThatUsesTheSetting();
}

Другое решение состоит в том, чтобы вызывать упомянутую функцию в промежутке между внесением изменений в переменные, которые использует функция const. Эта идея и решила мою проблему, так как я не был склонен изменять сигнатуру функции и должен был использовать метод changeASettingAndCallAFunction в качестве посредника:

Когда вы вызываете функцию, вы можете сначала внести изменения в настройку перед вызовом или (если вы не склонны возиться с вызывающим местом), возможно, вызвать функцию, где вам нужно изменить переменную для распространения (как в моем случае).

void SomeClass::someFunctionThatUsesTheSetting() const {
     //We really don't want to touch this functions implementation
     ClassUsesSetting* classUsesSetting = ClassUsesSetting::PropagateAcrossClass(someSetting);
     /*
         Do important stuff
     */
}

void SomeClass::changeASettingAndCallAFunction() const {
     someFunctionThatUsesTheSetting();
     /*
         Have to do this
     */
}

void SomeClass::nonConstInvoker(){
    someSetting = 0;
    changeASettingAndCallAFunction();
}

Теперь, когда вызывается какая-то ссылка на someFunctionThatUsesTheSetting, она вызывается с изменением someSetting.

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