Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
1

Свойство возвращает неконстантное значение

01.09.2015, 15:19. Показов 1248. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.

Разъясните мне, по какой такой причине нельзя было сделать возврат из свойства константного значения в VCL?
Например, хочу я в Caption у формы значение дописать, пишу:
C++
1
Caption += "suffix";
компилятор всё молча хавает, а в рантайме наблюдается облом, заголовок никак не меняется, потому что упомянутый код эквивалентен такому:
C++
1
2
auto c = Caption;
c += "suffix";
И тут уже видно, что Caption никак не изменяется, а изменяется его копия.
Приходится для работоспособности писать так:
C++
1
Caption = Caption + "suffix";
Что для любого, программирующего на C++ (без знаний подводных камней билдера), кажется избыточным.
Сделали бы возврат константы из свойства и код
C++
1
Caption += "suffix";
приводил бы к ошибке компиляции. Что было бы куда лучше, чем молча хавать.
Ваше мнение?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.09.2015, 15:19
Ответы с готовыми решениями:

Есть ли в компоненте chart свойство, которое возвращает текущую позицию
Привет. Подскажите есть ли в компоненте chart свойство, которое возвращает текущую позицию, которую...

Указатель не возвращает значение
BYTE* p_code; p_code =(BYTE*)VirtualAllocEx(hProcess, 0, sizeof(INJECTORCODE),MEM_COMMIT, ...

Функция не возвращает значение
double a12(element* vr,int nvr){ double s; for(int i=0;i<nvr-1;i++){ s +=...

Функция возвращает значение не полностью
void P(uint32_t *K,uint32_t *W){ uint8_t k, w; memcpy(w,W,32); for (int i=0;i<4;i++) for (int...

18
случайный прохожий
2935 / 1951 / 606
Регистрация: 20.07.2013
Сообщений: 5,159
02.09.2015, 02:28 2
Полагаю (если правильно понял "вопрос"), что [к примеру, для Caption] отсутствует "реализация" += либо стоит "заглушка".
Синтаксически все правильно - для String можно использовать +=, поэтому ошибки нет.
0
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 10:24 3
Цитата Сообщение от Tulosba Посмотреть сообщение
Разъясните мне, по какой такой причине нельзя было сделать возврат из свойства константного значения в VCL?
Вероятно потому, что VCL написано на Делфи, а Дефли не поддерживает обсуждаемые вами вещи. Точно так же, как и не поддерживает оператор +=, так что там аналогичных проблем не возникнет.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 12:23  [ТС] 4
Цитата Сообщение от gunslinger Посмотреть сообщение
отсутствует "реализация" += либо стоит "заглушка".
Отсутствие реализации или заглушка будет подразумевать, что Caption возвращает какой-то свой тип данных, а не UnicodeString (или другой String'о-подобный в зависимости от версии). Однако Caption возвращает именно строку (копию). В этом легко убедиться:
C++
1
2
UnicodeString s = Caption += "0"; // добавили "0" к КОПИИ строки заголовка. Заголовок ещё НЕ изменился.
Caption = s; // явно устанавливаем заголовок.
То что это именно копия, а не ссылка проверяется следующим кодом:
C++
1
UnicodeString& s = Caption;
Получим ошибку компиляции:
[BCC32 Error] E2357 Reference initialized with 'UnicodeString', needs lvalue of type 'UnicodeString'
Цитата Сообщение от kodv Посмотреть сообщение
Дефли не поддерживает обсуждаемые вами вещи
Какие конкретно моменты имеются в виду?

Любопытно заметить, что например целочисленные свойства типа Tag, Width, Height работают предсказуемо очевидным образом с +=. Т.е. как будто возвращают ссылку:
C++
1
Width += 1; // действительно меняет ширину формы
Хотя при записи:
C++
1
int& w = Width;
всё-таки получаем ошибку:
[BCC32 Error] E2034 Cannot convert 'const int' to 'int &'
Вероятно, нужно более подробно изучить как реализован механизм свойств в C++Builder/Rad Studio.
Если кто в курсе, буду признателен, если поделитесь информацией или ссылками.
0
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 12:48 5
Цитата Сообщение от Tulosba Посмотреть сообщение
Любопытно заметить, что например целочисленные свойства типа Tag, Width, Height работают предсказуемо очевидным образом с +=. Т.е. как будто возвращают ссылку:
Ссылка в любом случае не возвращается. Значение свойства меняется set-методом, а берется get-методом. Досконально работу компилятора не знаю, но, скорее всего,
C++
1
Width += 1;
Воспринимается как
C++
1
Width = Width + 1;
, что является поведение по-умолчанию, и что после посдтановки методов вместо свойств дает код
C++
1
SetWidth(GetWidth() + 1);
Но для String оператор += перегружен ... То есть, по итогу получается код
C++
1
GetCaption().operator +=("suffix");
То есть, в случае строки Set-метод не вызывается.
1
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
02.09.2015, 12:49 6
Tulosba, сравни:
C++
1
2
3
4
__property int Width = {read=FWidth, write=SetWidth, nodefault};
// где 
void __fastcall SetWidth(int Value);
// то есть, читается само поле FWidth, без геттера
и
C++
1
2
3
4
__property TCaption Caption = {read=GetText, write=SetText, stored=IsCaptionStored};
// где
TCaption __fastcall GetText(void);
void __fastcall SetText(const TCaption Value);
Все те свойства, которые без геттера - да будут нормально вести себя с "+=" и другими подобными операциями. Через геттер - разумеется, нет.
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 13:11  [ТС] 7
Цитата Сообщение от kodv Посмотреть сообщение
C++
1
Width += 1;
Воспринимается как
C++
1
Width = Width + 1;
Вот этот момент не до конца ясен. Если бы Width было обычным int'ом, то всё понятно.
Но Width это свойство, которое, как я понял, возвращает const int. А для целой константы += не применим.
Т.е. исходя из какой логики
C++
1
Width += 1;
превратилось в
C++
1
Width = Width + 1;
я пока не понимаю.

Цитата Сообщение от volvo Посмотреть сообщение
то есть, читается само поле FWidth, без геттера
С константностью этого поля что-то можешь пояснить?
Вот странно, если тут можем вернуть константу, то почему
Цитата Сообщение от Tulosba Посмотреть сообщение
нельзя было сделать возврат из свойства константного значения
в первоначальной постановке вопроса?
Особенно если
Цитата Сообщение от kodv Посмотреть сообщение
Дефли не поддерживает обсуждаемые вами вещи
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 13:14 8
Цитата Сообщение от Tulosba Посмотреть сообщение
Что для любого, программирующего на C++ (без знаний подводных камней билдера), кажется избыточным.
Сделали бы возврат константы из свойства и код
Да это лабуда, где-то они реализовали сокрашенные операции где-то нет, стоит лишь смериться с такой особенностью.

Добавлено через 2 минуты
Цитата Сообщение от Tulosba Посмотреть сообщение
Но Width это свойство, которое, как я понял, возвращает const int.
Ну вот констатность не предполагается, как видете в геттере нет константности, видать особенность переноса кода Delphi.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
02.09.2015, 13:15 9
Еще раз показать описание геттера? По-моему, там очень отчетливо видно, что возвращается новый экземпляр? А в случае Width работа происходит напрямую с полем FWidth, безо всяких сторонних методов, никаких новых экземпляров, поэтому там все работает как задумывалось.
Цитата Сообщение от Avazart Посмотреть сообщение
где-то они реализовали сокрашенные операции где-то нет
Еще одни писатель. Читать будем, или нет? Выше постом написано, где будут работать сокращенные операции, а где - нет. И почему было написано, только читать и понимать не все почему-то хотят. Атрофия мозга? Все, что выходит за рамки сортировки пузырьком или мерянья временем вычисления факториалов - уже вызывает сложности восприятия? Поменьше в разделах для начинающих сидеть не пробовали?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 13:26 10
Цитата Сообщение от volvo Посмотреть сообщение
Еще одни писатель. Читать будем, или нет? Выше постом написано, где будут работать сокращенные операции, а где - нет. И почему было написано, только читать и понимать не все почему-то хотят. Атрофия мозга? Все, что выходит за рамки сортировки пузырьком или мерянья временем вычисления факториалов - уже вызывает сложности восприятия? Поменьше в разделах для начинающих сидеть не пробовали?
Может я понимать вот просто не хочу, если не работает так не работает это плохо и все тут.
А по чему уже не колышыт.
Вопрос довольно очевиден, ибо поведение не очевидное.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 13:58  [ТС] 11
Запилил я такой класс:
C++
1
2
3
4
5
6
7
struct S {
    __property TCaption Caption = {read=FCaption, write=SetText};
    TCaption FCaption;
    void SetText(const TCaption& caption) {
        FCaption = caption;
    }
};
При чтении свойства компилятор всё же сам добавляет const к типу, если в read просто идет чтение поля:
C++
1
2
S s;
TCaption& c = s.Caption; // Cannot convert 'const UnicodeString' to 'UnicodeString &'
А вот если создать геттер как у TForm (надеюсь):
C++
1
2
3
4
5
6
7
8
9
10
struct S {
    __property TCaption Caption = {read=GetCaption, write=SetText};
    TCaption FCaption;
    void SetText(const TCaption& caption) {
        FCaption = caption;
    }
    TCaption GetCaption() const {
        return FCaption;
    }
};
Будем получать аналогичные приколы с += (модификация копии).

Хотя стоило-то всего лишь сделать:
C++
1
2
3
const TCaption GetCaption() const { // добавили const к возвращаемому типу
    return FCaption;
}
И на
C++
1
Caption += "suffix";
ожидаемо получим ошибку.

Но вот ПОЧЕМУ нельзя было так же сделать в VCL??? Снова дельфи виновата?
0
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 14:01 12
Цитата Сообщение от volvo Посмотреть сообщение
А в случае Width работа происходит напрямую с полем FWidth, безо всяких сторонних методов, никаких новых экземпляров, поэтому там все работает как задумывалось.
А если проверить? В случае int-го свойства при += setter вызывается в независимости от формы getter'а. И работает все верно для обоих вариантов getter'ов. Для String'а да, если в качестве getter'а указано поле, а не метод, то setter не вызывается.
Цитата Сообщение от Tulosba Посмотреть сообщение
Вот этот момент не до конца ясен. Если бы Width было обычным int'ом, то всё понятно.
Но Width это свойство, которое, как я понял, возвращает const int. А для целой константы += не применим.
В C++ свойств в принципе нет. В какой то момент при компиляции свойства заменяются на то, что находится после ключевых слов write и read. Конструкции вида a+=b, если оператор += не перегружен, также заменяются на a = a + b. Я предполагаю, что сначала a+=b, заменяется на a = a + b, а потом уже подставляются геттеры и сеттеры. Правда это всего лишь предположение.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 14:17 13
В RAD есть как бы генератор, который автоматом из паскалевских юнитов генирирует плюсовый заголовочный файл (для экспорта)
Вот многое зависит от того как он это делает (не всегда, очевидным/логичным способом)

Цитата Сообщение от Tulosba Посмотреть сообщение
Но вот ПОЧЕМУ нельзя было так же сделать в VCL??? Снова дельфи виновата?
Думаю можно было, вероятно решили не заморачивать, так же есть вариант что потом бы вылезло боком где-то в другом месте.
Кроме того в коде Delphi "не так часто встретишь константность"....
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 14:45  [ТС] 14
Цитата Сообщение от kodv Посмотреть сообщение
В C++ свойств в принципе нет.
Я в курсе Но билдер это не просто C++.
Цитата Сообщение от kodv Посмотреть сообщение
Конструкции вида a+=b, если оператор += не перегружен, также заменяются на a = a + b.
Это не так. Легко проверить, сделав свойство пользовательского типа, для которого оператор не перегружен. Получим ошибку компиляции, а не разворачивание:
E2093 'operator+=' not implemented in type 'T' for arguments of the same type

Не по теме:

Автоматическое разворачивание a+=b в a=a+b, если не ошибаюсь, реализовано в C#.


Цитата Сообщение от Avazart Посмотреть сообщение
Думаю можно было, вероятно решили не заморачивать, так же есть вариант что потом бы вылезло боком где-то в другом месте.
Печально. Боком, правда, вылезает уже сейчас (без const). Видимо придется просто с этим смириться.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 15:14 15
Цитата Сообщение от Tulosba Посмотреть сообщение
Печально. Боком, правда, вылезает уже сейчас (без const). Видимо придется просто с этим смириться.
Я бы не сказал что это так критично, все же это только в GUI части.
Да и учитывая экспорт с одного языка в другой и что есть куда более жесткие ограничения связаные с экспортом.


Добавлено через 52 секунды

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Автоматическое разворачивание a+=b в a=a+b, если не ошибаюсь, реализовано в C#.
Ну так там и модифицируемых строк нет.

0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 15:27  [ТС] 16
Цитата Сообщение от Avazart Посмотреть сообщение
все же это только в GUI части.
Почему только в GUI? Свойства ж где угодно могут быть.
В общем, хотелось бы конечно однозначно прояснить причину почему не добавили const. Пока что только догадки.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 15:31 17
Цитата Сообщение от Tulosba Посмотреть сообщение
Почему только в GUI? Свойства ж где угодно могут быть.
Могут, но как правило то их вводят для визуального программирования для отображения инспекторе объектов.
Ну а в Delphi это как бы "встроенный механизм", но только в делфи ссылочные типы, нет const в том смысле котором он С++ может быть, нет сокращенных операций.
0
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 18:50 18
Цитата Сообщение от Tulosba
Легко проверить, сделав свойство пользовательского типа, для которого оператор не перегружен.
Вы не правильно поняли, точнее, я не так выразился. Для пользовательского типа нужно явно перегружать оператор +=. По большому счету AnsiString тоже пользовательский тип. Я имел ввиду именно встроенные типы, для которых оператор += работает без перегрузки. Эти типы (int, char, float, double и др.) перекочевали в C++ из C, где оператор += не являлся перегружаемой функцией.
Цитата Сообщение от Tulosba
В общем, хотелось бы конечно однозначно прояснить причину почему не добавили const. Пока что только догадки.
Оно догадками и останется. Однозначно могут ответить только те, кто адаптировал VCL для BCB. Большинство hpp-файлов в VCL сгенерированы программно. Как генератор должен понять, где нужно подставить const, а где нет? const же накладывает свои ограничения, которые не обязательно учитывались при разработке VCL. Я думаю, что было проще и надежнее не внедрять const в библиотеки, где он не предусмотрен изначально.
В ту же тему свойств можно добавить невозможность множественого присваивания, которое является обыденным для C++:
C++
1
Edit1->Enabled = Edit2->Enabled = false;
Тоже раздражает, но с этим нужно смириться.
0
4043 / 2332 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
03.09.2015, 20:02 19
kodv, в точку, я так полагаю.
VCL ведь никто портировал, исходники на делфи. К ним прикрутили заголовки на плюсах и все. Отсюда все и всяческие приколы с неоднообразностью. Плюс к этому какие-то свойства можно модифицировать напрямую, те, что без сеттеров, какие-то - нет. Почему это так, а не иначе - это уж из области риторики. Разрабы сделали так и пользуйтесь, как хотите.
0
03.09.2015, 20:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.09.2015, 20:02
Помогаю со студенческими работами здесь

Не возвращает значение lpDisplayDevice.DeviceString
Пишу на C++ Builder XE Проблема в том, что не могу получить название видеокарты. //Информация о...

Свойство конструктора возвращает, но не принимает значение
Привет всем Есть конструктор public class pptxTableColumn:MyObj { MyObj...

Как вернуть в запросе значение по умолчанию, если SELECT возвращает NULL или ничего не возвращает?
Добрый день! Например я хочу чтобы донное выражение возвращало мне 0 или скажем 1, если...

XML, Свойство HasChildNodes всегда возвращает true
Добрый день! Помогите разобраться с XML есть простой файл XML: <?xml version="1.0"...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru