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

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

01.09.2015, 15:19. Показов 1513. Ответов 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
3190 / 2227 / 640
Регистрация: 20.07.2013
Сообщений: 6,023
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
33398 / 21508 / 8236
Регистрация: 22.10.2011
Сообщений: 36,906
Записей в блоге: 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
8488 / 6155 / 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
33398 / 21508 / 8236
Регистрация: 22.10.2011
Сообщений: 36,906
Записей в блоге: 12
02.09.2015, 13:15
Еще раз показать описание геттера? По-моему, там очень отчетливо видно, что возвращается новый экземпляр? А в случае Width работа происходит напрямую с полем FWidth, безо всяких сторонних методов, никаких новых экземпляров, поэтому там все работает как задумывалось.
Цитата Сообщение от Avazart Посмотреть сообщение
где-то они реализовали сокрашенные операции где-то нет
Еще одни писатель. Читать будем, или нет? Выше постом написано, где будут работать сокращенные операции, а где - нет. И почему было написано, только читать и понимать не все почему-то хотят. Атрофия мозга? Все, что выходит за рамки сортировки пузырьком или мерянья временем вычисления факториалов - уже вызывает сложности восприятия? Поменьше в разделах для начинающих сидеть не пробовали?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
Ответ Создать тему
Новые блоги и статьи
BOINC: 22 года — и всё ещё работает
Programma_Boinc 12.03.2026
BOINC: 22 года — и всё ещё работает Дэвид Андерсон написал ретроспективу. Кратко: в 2001 году он ушёл из United Devices, где был CTO, и за несколько месяцев написал ядро BOINC — клиент, сервер,. . .
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru