C++, избавление объекта от квалификатора const

173
07 октября 2018, 12:30

Хорошим тоном в C/C++ считается использование const везде, где можно.

Например:

void setName(const char *const _name)
{
    if (_name == nulltr)
    {
        return;
    }
    delete[] name;
    name = _name;
}

В данном примере const защищает от глупых ошибок, которые потом будет очень сложно найти. Проблема в том, что C++, в отличии от C, выдает предупреждениe при:

char *s;
const char *const cs;
s = (char*) cs;

А поскольку все современные библиотеки следуют хорошему тону использования const везде, где только можно, мне стало интересно, как лучше избавляться от квалификатора const в коде C++?

Использовать ли для этой цели const_cast или что-то иное?

Answer 1
char *s;
const char *cs;
s = const_cast<char*>(cs);

Но тут возникает вопрос, а для чего Вам нужно избавляться от квалификатора const?

Использование const_cast необходимо лишь для совместимости с библиотеками, написанными на Си, где const не было, и лишь в том случае, если мы знаем что метод гарантировано не вносит в переменную изменений.

В Вашем случае, я так понимаю что переменная name имеет тип char*, и если Вы присвоите ей значение _name с помощью const_cast, то никто не гарантирует что в другом методе Вы не захотите изменить name, чем поменяете и исходный _name.

Думаю, что Вам необходимо просто скопировать себе строку и дальше делать с неё что угодно.

void setName(const char *const _name)
{
    if (_name == nulltr)
    {
        return;
    }
    delete[] name;
    const int strSize = strlen(_name);
    name = new char(strSize + 1);
    strcpy(name, _name);
    name = _name;
}

Дополнено Если объект все таки нужно сохранить как член класса, то можно его тоже объявить как константный:

class MyClass
{
public:
    void setName(const char *const _name)
    {
        if (_name == nullptr)
        {
            return;
        }
        name = _name;
    }
    const char *name = nullptr;
};
int main(int argc, char *argv[])
{
    MyClass v;
    v.setName("My Name");
}

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

Дополнение2

Если прям хотите уберечь себя от случайного изменения объекта, используйте временную константную переменную:

class MyClass
{
public:
    void setName(char *_name)
    {
        const char * const tempName = _name;
        //тут делаем дофига операций с tempName
        name = _name;
    }
    char *name = nullptr;
};

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

Answer 2

Гм...

Хорошим тоном в C/C++ считается использование const везде, где можно.

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

Например,

int square(const int x) { return x*x; }

Да, тут можно писать const - но вот нужно ли? Чего вы этим добьетесь?

Избавляться от const в коде С++ необходимо по сути только при работе с уже имеющимся кодом, в котором не использован const, но ведет код себя так, как будто он написан (причем это поведение гарантируется и в будущих версиях). И то - бывает, что надежнее сделать не-const копию и отдать ее такому старому коду, особенно если такой гарантии будущего константного поведения нет...

READ ALSO
Значения с С++ в QML

Значения с С++ в QML

С СОМ порта мне приходят данные, например: 19999932

152
Ошибка при инжекте DLL-файла

Ошибка при инжекте DLL-файла

Возникла ошибка, при инжекте собственного DLL-файла в игру

264
Как получить Bitmap из Gif?

Как получить Bitmap из Gif?

Простым открытием файла не получаетсяПримерный код:

192