3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|||||||||||
1 | |||||||||||
Константные методы19.08.2020, 09:04. Показов 5975. Ответов 20
Здравствуйте.
Потихоньку изучаю С++. Разобрался в идее константных методов?! Они нужны для того, чтобы константный объект мог эти методы вызывать? Но тогда почему работает такой код? Кликните здесь для просмотра всего текста
почему метод get мб константным? Вернув указатель, я могу разыменовывать его, и тем самым изменить состояние объекта? Почему такой код компилируется? Такой код у меня не компилируется. Кликните здесь для просмотра всего текста
К чему я всё это веду? Ковыряя умные указатели, я обнаружил что метод get() класса std::unique_ptr константный. Зачем это было сделано? В чём смысл?
0
|
19.08.2020, 09:04 | |
Ответы с готовыми решениями:
20
Константные поля и методы Константные методы и объекты класса Дублирование кода и константные методы Константные методы в абстрактных классах |
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 09:16 | 2 |
Да. Они нужны для того, чтобы эти методы можно было вызывать в т.ч. через константный объект.
Ым... Вы же сами сказали: чтобы константный объект мог эти методы вызывать. А кто вам сказал, что массив arr является частью "состояния объекта"? Это может быть совершенно посторонний массив. Ваш объект просто хранит указатель на этот совершенно посторонний массив зачем-то (кто его знает, зачем), но массив не является частью "состояния объекта".Так эту ситуацию видит язык С++. Язык С++ не знает, что вы лично хотели реализовать. Язык С++ не знает, является ли массив arr частью "состояния объекта" или не является.Если вы хотите, чтобы массив arr являлся частью "состояния объекта", то эта ваша обязанность, обеспечить правильную делегацию константности, т.е. сделать так, чтобы этот массив нельзя было модифицировать для константных объектов. Это ваша обязанность возвращать именно const int * из такого константного метода. Тут все в ваших руках: как напишете, так и будет.А что это за белиберда вообще? Что такое const_m[0] ? Разумеется, это не будет компилироваться. Но не ясно, как это относится к теме.В том что модификация самого указателя и модификация указуемых данных - это совершенно разные, никак не связанные друг с другом вещи. Константность указателя означает, что нельзя модифицировать сам указатель, но совсем не означает что нельзя модифицировать указуемые данные. Константность метода get означает только то, что он не модифицирует сам умный указатель. Благодаря этому вы можете вызывать get для константных указателей. В этом и заключается смысл.
1
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
||||||||||||||||
19.08.2020, 09:18 [ТС] | 3 | |||||||||||||||
TheCalligrapher, спасибо за ответ.
Сигнатура метода get(), наверное, такая?
Ошибся. Извините. Вот так у меня компилируется и работает. Кликните здесь для просмотра всего текста
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 09:23 | 4 |
Я говорю именно о константности самого "умного указателя", а не константности возвращаемого значения
get .Нет, конечно. Это бессмыслица какая-то. Константность верхнего уровня для возвращаемого значения функции, когда это возвращаемое значение имеет скалярный тип (напр. обычный указатель) - это бессмыслица, которая ничего не дает вообще. (Эта константность влияет на тип функции, но более никакого практического смысла не имеет.) Нет, не получается.
0
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|
19.08.2020, 09:27 [ТС] | 5 |
Я хотел выразить идею, что указатель константный. Что нельзя заставить его ссылать на другую память? Разве это не так делается?
Что даёт константность умного указателя? Зачем это мб нужно?
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 09:33 | 6 |
Это нормально. Ваша реализация
MyClass фактически говорит о том, что массив arr внутри MyClass НЕ является частью состояния MyClass . Соответственно, константность MyClass НЕ распространяется на массив arr ."Заставить ссылаться на другую память" можно только переменную типа указатель, то есть изменяемое lvalue. Скалярный результат работы функции get - это не переменная, это просто эфемерное значение, rvalue. Его невозможно поменять в принципе. К нем вообще неприменимо понятие "поменять". Поэтому и навешивать на него const верхнего уровня нет никакого смысла. Например, результат выражения 2+3 имеет тип int . Обратите внимание: int , а не const int . Это, однако, не значит, что вы можете каким-то образом "поменять" результат выражения 2+3 . То же самое относится и к результату метода get : вы не можете его поменять, независимо от того, есть на нам const или нет.Как это "зачем"? Допустим вы хотите, чтобы этот указатель всегда указывал в одно и то же место. Т.е чтобы такой указатель никто не мог поменять (т.е. перенаправить в другое место). Вот для этого вы и делаете его константным.
1
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|||||||||||
19.08.2020, 09:40 [ТС] | 7 | ||||||||||
Но я и так не могу его поменять?
Вот мой простой класс. Кликните здесь для просмотра всего текста
Вот его использование. Кликните здесь для просмотра всего текста
Я ведь не могу сделать так? У меня не будет компилироваться? Аналогично, и с unique_ptr. Я никак не могу заставить его ссылать на другую область памяти. И константным его делать мне не нужно. Следовательно, делать константным метод get тоже.
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
||||||
19.08.2020, 09:52 | 8 | |||||
Как это "не можете"? У стандартных умных указателей есть модифицирующие методы, которые их меняют, т.е. перенаправляют в новое место. Например, у
std::unique_ptr есть метод reset . И оператор присваивания у него тоже есть. И метод swap .Разумеется, все эти методы - неконстантны. То есть вызвать их для константного std::unique_ptr вы не сможете.Для вашего класса? Да, именно так вы сделать не сможете. А вот так - сможете
a изменится (с катастрофическими последствиями). Если бы a был const , то выполнить такое присваивание вы бы не смогли.
1
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
||||||
19.08.2020, 10:10 [ТС] | 9 | |||||
TheCalligrapher, спасибо. Я разобрался.
Добавлено через 11 минут TheCalligrapher, получается, что в моё случае, правильная реализация идеи константности, заключается в ведение метода get_const(). Тем самым я говорю, что указатель arr - это моё состояние?! Кликните здесь для просмотра всего текста
А метод get, в таком случае можно сделать не константным?!
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
||||||
19.08.2020, 10:13 | 10 | |||||
schoolboy_, у вас может быть два метода
get , один константный, другой - нет.
get вы не сможете вызвать на константном объекте MyClass, а второй - сможете.
1
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|
19.08.2020, 10:15 [ТС] | 11 |
Погодите. Такого быть не может? Если есть оператор присваивания, то вся идея уникального указателя пропадает? Есть Есть перемещающий оператор присваивания? Вы его имели в виду?
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 10:16 | 12 |
Зачем? То есть можно так, но элегантнее будет просто применить перегрузку функций, т.е. сделать так, как показал DrOffset.
0
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
||||||
19.08.2020, 10:20 [ТС] | 13 | |||||
вы предлагает сделать так?
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 10:24 | 14 |
Сообщение было отмечено schoolboy_ как решение
Решение
Если ваш указатель должен быть уникальным, то это ваша задача - реализовать эту уникальность так, как вы ее себе представляете. Либо запретить присваивание вообще, либо сделать его перемещающим (как в
std::unique_ptr ), либо еще как-то...Вы же сами сказали, что у вас содержимое arr является частью состояния MyClass . Ну так тогда, наверное, правильнее будет сделать оператор присваивания, который будет копировать не указатель, а именно содержимое arr ?В любом случае: все определяется вашим замыслом. Что вы реализуете, то и получится в результате. Все в ваших руках. Посмотрите внимательнее, что написано в коде у DrOffset. Там не так. Не понял. Что именно является частью состояния? Только сам указатель? Или и указуемые данные тоже?
0
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
||||||
19.08.2020, 10:24 [ТС] | 15 | |||||
Понятно. Никто ведь не может помешать мне написать такой код:
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 10:26 | 16 |
0
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|
19.08.2020, 10:34 [ТС] | 17 |
Указатель всегда является частью состояния? Я не могу его никак изменить при такой реализации. А если я хочу чтобы константный объект не мог менять ещё и данные, то я должен сделать так, как написал DrOffset?
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|
19.08.2020, 10:39 | 18 |
Да, сам указатель
arr всегда является частью состояния MyClass . Если весь объект MyClass константен, то и указатель arr константен. Поменять сам указатель в такой ситуации вы не можете ни при какой реализации. (Кроме случая, когда вы сами объявили этот указатель как mutable )Именно так. "По умолчанию" константность MyClass не распространяется на указуемые данные. Распространить константность MyClass на указуемые данные можно только аккуратной реализацией такого "распространения" вручную. Например так, как показал DrOffset.
1
|
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
|
|||||||||||
19.08.2020, 11:06 [ТС] | 19 | ||||||||||
Ещё такой вопрос. Я добавил в свой класс две функции
0
|
Вездепух
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,877
|
|||||||||||
19.08.2020, 11:09 | 20 | ||||||||||
Можно так
В данном случае объект m неконстантен, но вы как бы создаете константный "пусть доступа" к нему - ссылку (или указатель). И уже через этот "пусть доступа" вызываете константный метод. Менее громоздких способов нет.
1
|
19.08.2020, 11:09 | |
19.08.2020, 11:09 | |
Помогаю со студенческими работами здесь
20
Константные и неконстантные методы в классе Константные и не константные ссылки. Приведения типов. Нужно уточнение Константные объекты Константные функции Константные функции-члены Константные поля класса Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |