Форум программистов, компьютерный форум CyberForum.ru

Модификатор const Очередные грабли с++? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 22, средняя оценка - 4.68
Bers
Заблокирован
21.10.2011, 21:15     Модификатор const Очередные грабли с++? #1
Представленный ниже код не компилируется.
В чем здесь может быть проблема?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CFirst
{
public:
    int GetValue() { return 10; }
};
 
class CSecond
{
public:
    void Do(const CFirst& src) const
    {
        if(src.GetValue()==10) { std::cout<<"YES!\n"; }
    }
};

error C2662: CFirst::GetValue: невозможно преобразовать указатель 'this' из 'const CFirst' в 'CFirst &'

Если убрать модификатор const все работает без проблем.
Я уже заколебался ловить баги с этими констами.
Оказывается, они даже жизнь временных объектов умеют продлевать.
Но здесь же в условии сам объект класса CFirst вообще не трогается.
Число 10 сравнивается с временным int, и контракт CFirst не нарушается!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.10.2011, 21:15     Модификатор const Очередные грабли с++?
Посмотрите здесь:

модификатор const в аргументах функций C++
C++ Чисто виртуальные классы. Модификатор const
Cannot convert 'const wchar_t *' to 'const char *' C++
char operator[](unsigned short offset) const; // что означает const? C++
C++ Что это bool operator== (const CLASS&) const;
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
21.10.2011, 21:18     Модификатор const Очередные грабли с++? #2
C++
1
2
3
4
5
class CFirst
{
public:
    int GetValue() const { return 10; }
};
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.10.2011, 21:19     Модификатор const Очередные грабли с++? #3
Цитата Сообщение от Bers Посмотреть сообщение
int GetValue() { return 10; }
компилятору не в домёк что эта функция не меняет состояние объекта потому
Цитата Сообщение от Bers Посмотреть сообщение
error C2662: CFirst::GetValue: невозможно преобразовать указатель 'this' из 'const CFirst' в 'CFirst &'
все законно
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
21.10.2011, 21:20     Модификатор const Очередные грабли с++? #4
src - объявлен как ссылка на константный объект, а значит к этому объекту могут быть применены только константные методы, которым GetValue не является
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
21.10.2011, 21:20     Модификатор const Очередные грабли с++? #5
Все как раз четко. Откуда компилятор знает, что происходит в CFirst::GetValue(). ИИ не наделен пока.
Bers
Заблокирован
21.10.2011, 21:29  [ТС]     Модификатор const Очередные грабли с++? #6
Цитата Сообщение от Jupiter Посмотреть сообщение
компилятору не в домёк что эта функция не меняет состояние объекта потому
ааа.... Но он же как то умеет фиксить нарушения контрактов аля int GetValue() const { return 10; }

Значит он умеет определять может ли функция изменить состояние объекта, или нет.

Добавлено через 46 секунд
Цитата Сообщение от gooseim Посмотреть сообщение
Все как раз четко. Откуда компилятор знает, что происходит в CFirst::GetValue(). ИИ не наделен пока.
Если функция нарушит контракт int GetValue() const;
Он же об этом как то узнает

Добавлено через 5 минут
А вот в этом случае что можно сделать? Снимать константность?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CFirst
{
    int LastError;
    void CheckError() { LastError=1; }
public:
    int GetValue()  
    { 
        CheckError();
        return 10; 
    }
 
};
 
class CSecond
{
public:
    void Do(const CFirst& src) const
    {
        if(10==src.GetValue()) { std::cout<<"YES!\n"; }
    }
};
У меня нет возможности сделать метод int GetValue() const
Потому что CheckError() всегда может изменить состояние объекта.
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
21.10.2011, 21:33     Модификатор const Очередные грабли с++? #7
Цитата Сообщение от Bers Посмотреть сообщение
Если функция нарушит контракт int GetValue() const;
Он же об этом как то узнает
А если эта функция не в исходнике а в библиотеке?

Добавлено через 1 минуту
Решение простое:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CFirst
{
    mutable int LastError;
    void CheckError() const { LastError=1; }
public:
    int GetValue() const
    { 
        CheckError();
        return 10; 
    }
 
};
 
class CSecond
{
public:
    void Do(const CFirst& src) const
    {
        if(10==src.GetValue()) { std::cout<<"YES!n"; }
    }
};
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.10.2011, 21:38     Модификатор const Очередные грабли с++? #8
Цитата Сообщение от Bers Посмотреть сообщение
ааа.... Но он же как то умеет фиксить нарушения контрактов аля int GetValue() const { return 10; }
Значит он умеет определять может ли функция изменить состояние объекта, или нет.
все его умение заключается в отслеживании модификатора const для методов

Добавлено через 1 минуту
вот еще один пример валидного кода
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CFirst
{
public:
    constexpr int GetValue() { return 10; }
};
 
class CSecond
{
public:
    void Do(const CFirst& src) const
    {
        if(src.GetValue()==10) { std::cout<<"YES!\n"; }
    }
};
возвращаемое значение вычислимо на этапе компиляции - следовательно оно не может изменить состояние объекта

Добавлено через 40 секунд
http://liveworkspace.org/code/a211a1...1cb16fe44adee0
Bers
Заблокирован
21.10.2011, 21:46  [ТС]     Модификатор const Очередные грабли с++? #9
Цитата Сообщение от Jupiter Посмотреть сообщение
возвращаемое значение вычислимо на этапе компиляции - следовательно оно не может изменить состояние объекта
Утром вычислимое, к вечеру уже может и не вычисляться)
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
21.10.2011, 21:47     Модификатор const Очередные грабли с++? #10
Цитата Сообщение от Bers Посмотреть сообщение
Потому что CheckError() всегда может изменить состояние объекта.
Тогда зачем делать константным src, если известно что он может быть изменен?
Bers
Заблокирован
21.10.2011, 21:51  [ТС]     Модификатор const Очередные грабли с++? #11
Цитата Сообщение от Net_Wanderer Посмотреть сообщение
Тогда зачем делать константным src, если известно что он может быть изменен?
метод void Do(const CFirst& src) const
заключает контракт с классом CFirst, обещая ему, что никогда, ни при каких обстоятельствах не попытается изменить состояние объекта src

То, что src может изменится сам (его внутренняя работа. Может там в другом потоке с ним кто-то что делает) - метода Do() вообще никак не касается.


И ещё: СВЯТАЯ ИНКАПСУЛЯЦИЯ. Класс CSecond разрабатывает совсем другой человек, который понятия не имеет, как устроен изнутри CFirst
CFirst сам должен позаботится о том, что бы не создавать проблем конечным пользователям
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
21.10.2011, 23:07     Модификатор const Очередные грабли с++? #12
Цитата Сообщение от Bers Посмотреть сообщение
заключает контракт с классом CFirst, обещая ему, что никогда, ни при каких обстоятельствах не попытается изменить состояние объекта src
void Do(const CFirst& src) const - указывает на то, что объект не изменит себя
void Do(const CFirst& src) const - указывает на то, что объект src константный, т.е. который не изменяется ни сам, ни при помощи кого-то, а не то, что данный метод не будет его изменять

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
И ещё: СВЯТАЯ ИНКАПСУЛЯЦИЯ. Класс CSecond разрабатывает совсем другой человек, который понятия не имеет, как устроен изнутри CFirst
CFirst сам должен позаботится о том, что бы не создавать проблем конечным пользователям
Это правильно. Поэтому нужно изначально правильно его проектировать.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.10.2011, 23:13     Модификатор const Очередные грабли с++?
Еще ссылки по теме:

C++ const& и const* в имени функции
C++ int const * const foo(const int* param) const - разъясните значение квалификаторов
C++ Const в параметрах. Перед чем нужно употребить const дабы обезопасить данные от изменения

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Bers
Заблокирован
21.10.2011, 23:13  [ТС]     Модификатор const Очередные грабли с++? #13
Цитата Сообщение от gooseim Посмотреть сообщение
void Do(const CFirst& src) const - указывает на то, что объект src константный, т.е. который не изменяется ни сам, ни при помощи кого-то, а не то, что данный метод не будет его изменять
ну.. я очень надеюсь, что mutable спасет отца русской демократии))
Yandex
Объявления
21.10.2011, 23:13     Модификатор const Очередные грабли с++?
Ответ Создать тему
Опции темы

Текущее время: 09:31. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru