Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 22, средняя оценка - 4.68
Bers
Заблокирован
#1

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

21.10.2011, 21:15. Просмотров 3164. Ответов 12
Метки нет (Все метки)

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

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 не нарушается!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.10.2011, 21:15
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Модификатор const Очередные грабли с++? (C++):

Модификатор const для параметра функции не const? - C++
void foo(const int N) { int Arr; //&lt;-- ??? } В clang это работает. В VisualStudio 2015 нет.

Модификатор доступа const - C++
Здравсвуйте, прошу помочь с вопросом. В общем имеется такой класс: class Animator : public sf::Drawable { private: ...

Модификатор const в аргументах функций - C++
Постоянно путаюсь в этих константах. Как писать грамотнее? Вот так: template&lt;typename TypeT&gt; void...

Модификатор const в качестве возвращаемого значения - C++
const int get_size(const int&amp; a) { return a; } int main() { const int size = get_size(5);

Чисто виртуальные классы. Модификатор const - C++
Приветствую всех! Известно, что чисто виртуальный (абстрактный) класс можно получить class A { public: virtual void test()=0; };...

int const * const foo(const int* param) const - разъясните значение квалификаторов - C++
int const * const foo(const int* param) const -----1------2----------3----------------4 1: ? 2: делает содержимое массива или...

12
gooseim
Эксперт С++
508 / 412 / 37
Регистрация: 23.09.2010
Сообщений: 1,159
21.10.2011, 21:18 #2
C++
1
2
3
4
5
class CFirst
{
public:
    int GetValue() const { return 10; }
};
0
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.10.2011, 21:19 #3
Цитата Сообщение от Bers Посмотреть сообщение
int GetValue() { return 10; }
компилятору не в домёк что эта функция не меняет состояние объекта потому
Цитата Сообщение от Bers Посмотреть сообщение
error C2662: CFirst::GetValue: невозможно преобразовать указатель 'this' из 'const CFirst' в 'CFirst &'
все законно
0
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
21.10.2011, 21:20 #4
src - объявлен как ссылка на константный объект, а значит к этому объекту могут быть применены только константные методы, которым GetValue не является
0
gooseim
Эксперт С++
508 / 412 / 37
Регистрация: 23.09.2010
Сообщений: 1,159
21.10.2011, 21:20 #5
Все как раз четко. Откуда компилятор знает, что происходит в CFirst::GetValue(). ИИ не наделен пока.
0
Bers
Заблокирован
21.10.2011, 21:29  [ТС] #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() всегда может изменить состояние объекта.
0
gooseim
Эксперт С++
508 / 412 / 37
Регистрация: 23.09.2010
Сообщений: 1,159
21.10.2011, 21:33 #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"; }
    }
};
2
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.10.2011, 21:38 #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/a211a1eccaba4705c51cb16fe44adee0
1
Bers
Заблокирован
21.10.2011, 21:46  [ТС] #9
Цитата Сообщение от Jupiter Посмотреть сообщение
возвращаемое значение вычислимо на этапе компиляции - следовательно оно не может изменить состояние объекта
Утром вычислимое, к вечеру уже может и не вычисляться)
1
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
21.10.2011, 21:47 #10
Цитата Сообщение от Bers Посмотреть сообщение
Потому что CheckError() всегда может изменить состояние объекта.
Тогда зачем делать константным src, если известно что он может быть изменен?
0
Bers
Заблокирован
21.10.2011, 21:51  [ТС] #11
Цитата Сообщение от Net_Wanderer Посмотреть сообщение
Тогда зачем делать константным src, если известно что он может быть изменен?
метод void Do(const CFirst& src) const
заключает контракт с классом CFirst, обещая ему, что никогда, ни при каких обстоятельствах не попытается изменить состояние объекта src

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


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

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
И ещё: СВЯТАЯ ИНКАПСУЛЯЦИЯ. Класс CSecond разрабатывает совсем другой человек, который понятия не имеет, как устроен изнутри CFirst
CFirst сам должен позаботится о том, что бы не создавать проблем конечным пользователям
Это правильно. Поэтому нужно изначально правильно его проектировать.
0
Bers
Заблокирован
21.10.2011, 23:13  [ТС] #13
Цитата Сообщение от gooseim Посмотреть сообщение
void Do(const CFirst& src) const - указывает на то, что объект src константный, т.е. который не изменяется ни сам, ни при помощи кого-то, а не то, что данный метод не будет его изменять
ну.. я очень надеюсь, что mutable спасет отца русской демократии))
0
21.10.2011, 23:13
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.10.2011, 23:13
Привет! Вот еще темы с ответами:

char operator[](unsigned short offset) const; // что означает const? - C++
Собстенно вопрос уже озвучен :).

Что это bool operator== (const CLASS&) const; - C++
Что это? class CLASS { public: bool operator== (const CLASS&amp;) const; ...

Const в параметрах. Перед чем нужно употребить const дабы обезопасить данные от изменения - C++
const int Counter(const TSNum *Start) { int c=0; while(Start!=NULL){Start=Start-&gt;next;} return c; } Функция...

Ошибка: Cannot convert 'char const[18]' to 'const wchar_t *' - C++
Unit1.cpp(59): E2034 Cannot convert 'char const' to 'const wchar_t *' Full parser context Unit1.cpp(55): parsing: void _fastcall...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.