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

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

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

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

Разъясните мне, по какой такой причине нельзя было сделать возврат из свойства константного значения в 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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.09.2015, 15:19
Ответы с готовыми решениями:

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

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

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

18
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,009
02.09.2015, 02:28
Полагаю (если правильно понял "вопрос"), что [к примеру, для Caption] отсутствует "реализация" += либо стоит "заглушка".
Синтаксически все правильно - для String можно использовать +=, поэтому ошибки нет.
0
 Аватар для kodv
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 10:24
Цитата Сообщение от Tulosba Посмотреть сообщение
Разъясните мне, по какой такой причине нельзя было сделать возврат из свойства константного значения в VCL?
Вероятно потому, что VCL написано на Делфи, а Дефли не поддерживает обсуждаемые вами вещи. Точно так же, как и не поддерживает оператор +=, так что там аналогичных проблем не возникнет.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 12:23  [ТС]
Цитата Сообщение от 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
 Аватар для kodv
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 12:48
Цитата Сообщение от 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
 Аватар для volvo
33195 / 21491 / 8233
Регистрация: 22.10.2011
Сообщений: 36,879
Записей в блоге: 12
02.09.2015, 12:49
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  [ТС]
Цитата Сообщение от 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
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 13:14
Цитата Сообщение от Tulosba Посмотреть сообщение
Что для любого, программирующего на C++ (без знаний подводных камней билдера), кажется избыточным.
Сделали бы возврат константы из свойства и код
Да это лабуда, где-то они реализовали сокрашенные операции где-то нет, стоит лишь смериться с такой особенностью.

Добавлено через 2 минуты
Цитата Сообщение от Tulosba Посмотреть сообщение
Но Width это свойство, которое, как я понял, возвращает const int.
Ну вот констатность не предполагается, как видете в геттере нет константности, видать особенность переноса кода Delphi.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33195 / 21491 / 8233
Регистрация: 22.10.2011
Сообщений: 36,879
Записей в блоге: 12
02.09.2015, 13:15
Еще раз показать описание геттера? По-моему, там очень отчетливо видно, что возвращается новый экземпляр? А в случае Width работа происходит напрямую с полем FWidth, безо всяких сторонних методов, никаких новых экземпляров, поэтому там все работает как задумывалось.
Цитата Сообщение от Avazart Посмотреть сообщение
где-то они реализовали сокрашенные операции где-то нет
Еще одни писатель. Читать будем, или нет? Выше постом написано, где будут работать сокращенные операции, а где - нет. И почему было написано, только читать и понимать не все почему-то хотят. Атрофия мозга? Все, что выходит за рамки сортировки пузырьком или мерянья временем вычисления факториалов - уже вызывает сложности восприятия? Поменьше в разделах для начинающих сидеть не пробовали?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 13:26
Цитата Сообщение от volvo Посмотреть сообщение
Еще одни писатель. Читать будем, или нет? Выше постом написано, где будут работать сокращенные операции, а где - нет. И почему было написано, только читать и понимать не все почему-то хотят. Атрофия мозга? Все, что выходит за рамки сортировки пузырьком или мерянья временем вычисления факториалов - уже вызывает сложности восприятия? Поменьше в разделах для начинающих сидеть не пробовали?
Может я понимать вот просто не хочу, если не работает так не работает это плохо и все тут.
А по чему уже не колышыт.
Вопрос довольно очевиден, ибо поведение не очевидное.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 13:58  [ТС]
Запилил я такой класс:
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
 Аватар для kodv
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 14:01
Цитата Сообщение от 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
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 14:17
В RAD есть как бы генератор, который автоматом из паскалевских юнитов генирирует плюсовый заголовочный файл (для экспорта)
Вот многое зависит от того как он это делает (не всегда, очевидным/логичным способом)

Цитата Сообщение от Tulosba Посмотреть сообщение
Но вот ПОЧЕМУ нельзя было так же сделать в VCL??? Снова дельфи виновата?
Думаю можно было, вероятно решили не заморачивать, так же есть вариант что потом бы вылезло боком где-то в другом месте.
Кроме того в коде Delphi "не так часто встретишь константность"....
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.09.2015, 14:45  [ТС]
Цитата Сообщение от 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
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 15:14
Цитата Сообщение от 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  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
все же это только в GUI части.
Почему только в GUI? Свойства ж где угодно могут быть.
В общем, хотелось бы конечно однозначно прояснить причину почему не добавили const. Пока что только догадки.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2015, 15:31
Цитата Сообщение от Tulosba Посмотреть сообщение
Почему только в GUI? Свойства ж где угодно могут быть.
Могут, но как правило то их вводят для визуального программирования для отображения инспекторе объектов.
Ну а в Delphi это как бы "встроенный механизм", но только в делфи ссылочные типы, нет const в том смысле котором он С++ может быть, нет сокращенных операций.
0
 Аватар для kodv
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
02.09.2015, 18:50
Цитата Сообщение от 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
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
03.09.2015, 20:02
kodv, в точку, я так полагаю.
VCL ведь никто портировал, исходники на делфи. К ним прикрутили заголовки на плюсах и все. Отсюда все и всяческие приколы с неоднообразностью. Плюс к этому какие-то свойства можно модифицировать напрямую, те, что без сеттеров, какие-то - нет. Почему это так, а не иначе - это уж из области риторики. Разрабы сделали так и пользуйтесь, как хотите.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
03.09.2015, 20:02
Помогаю со студенческими работами здесь

Функция возвращает значение не полностью
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 j=1;j<9;j++) k = w; for(int i =...

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru