Войти
ПрограммированиеФорумОбщее

Вопросы по Delphi (54 стр)

Страницы: 153 54 55 5658 Следующая »
#795
(Правка: 18:16) 18:10, 7 ноя 2022

g-cont

   
  TWMSysCommand = packed record
     Msg: Cardinal;
     case CmdType: Longint of

с точки зрения компилятора это тоже самое что и

   
  TWMSysCommand = packed record
     Msg: Cardinal;
     CmdType: Longint;
     case Longint of

Но первый вариант дает подсказку-комментарий программисту что CmdType это поле содержащее тэг юниона.

Возможно когда-то были планы учитывать тэг для чего-нибудь, но видимо они остались нереализованными.

#796
18:23, 7 ноя 2022

g-cont
>однако к CmdType обращаются в коде, как к реальной переменной.

Для case именно переменная необязательна, нужно чтобы на выходе результат, с которым работают был переменной. Вот так тоже работает:

function abvgd: byte;
begin
result:=random(100);
end; 

begin
randomize;
case abvgd of
-1000..1000: writeln(abvgd);
end;
end.
#797
(Правка: 0:03) 0:00, 8 ноя 2022

g-cont
> Как вот этот юнион устроен?

__attribute__((packed))
struct wm_sys_command_t {
    unsigned msg;
    long cmd_type;
    union {
        HWND activate_wnd;
        unsigned short key;
        struct {
            short xpos, ypos;
            long result;
        };
    };
};

Да, CmdType - это просто переменная, а метки в кейсе - чисто декоративные.


Изначально, в паскале "юнионы" были только с тегом - в заголовке кейса обязательно должна быть переменная, а метки кейса - это значения переменной-тега. Какое значение стоит у тега - тот вариант и активен.
Но потом, насмотревшись на безтеговые юнионы в сишке, их решили ввести и в новую версию паскаля - для этого, взяли уже имеющийся синтаксис кейс-рекорда, и тупо убрали имя переменной. Костыль успешно приклеен.

И да, слово packed в объявлении рекорда - это модификатор, который означает, что поля должны идти в сплошную друг за другом, без пропусков и выравниваний.

#798
10:56, 8 ноя 2022

Любопытно, что С++, который начинался как фронтэнд-препроцессор, оказался более целостным, нежели Делфи с персональным бакэндом.
Хотя казалось бы, у последних было куда больше возможностей всё сделать красиво и логично.

#799
11:36, 8 ноя 2022

По какому принципу в Dlphi осуществляется неявное приведение типов?
Вот например

procedure TWinControl.GetTabOrderList(List: TList);
var
  I: Integer;
  Control: TWinControl;
begin
  if FTabList <> nil then
    for I := 0 to FTabList.Count - 1 do
    begin
      Control := FTabList[I];
      List.Add(Control);
      Control.GetTabOrderList(List);
    end;
end;

FTabList это обычный TList-контейнер, хранит в себе указатели на TObject и без каких-либо преобразований и проверок на NULL неявно приводится к TWinControl. Здесь по смыслу нужен dynamic_cast, но компилятор, судя по всему вставляет static_cast и скорее всего делает это без каких-либо предупреждений.

#800
(Правка: 11:59) 11:54, 8 ноя 2022

g-cont

В той делфи что у меня под рукой написано так:

procedure TWinControl.GetTabOrderList(List: TList);
var
  I: Integer;
  Control: TWinControl;
begin
  if FTabList <> nil then
    for I := 0 to FTabList.Count - 1 do
    begin
      Control := TWinControl(FTabList[I]);
      List.Add(Control);
      Control.GetTabOrderList(List);
    end;
end;

Так же нужно понимать, что исходники RTL/VCL не обязательно должны быть компилируемыми и могут содержать ошибки.
RTL/VCL поставляется в виде скомпилированных .dcu/.dcp модулей с отладочной инфой, а исходники поставляются чтобы можно было отладчиком заходить в этот уже скомпилированный код.
Компилирование RTL/VCL самостоятельно не предполагается.

#801
11:57, 8 ноя 2022

CD

+1

#802
12:11, 8 ноя 2022

CD
> Так же нужно понимать, что исходники RTL/VCL не обязательно должны быть
> компилируемыми и могут содержать ошибки.
То есть уже готовые модули компилируются из каких-то других исходников? 0_о
У меня Borland Delphi v.7.0 Enterprise и там оно вот так, как я привёл. В принципе, если бы мне что-то глаз резануло, я бы давно забил тревогу,
но ничего, кроме вольного обращения с типами я больше не заметил.

а какой тэг используется для подсветки паскаля?

#803
(Правка: 13:10) 12:36, 8 ноя 2022

g-cont
>То есть уже готовые модули компилируются из каких-то других исходников?

Как производитель делает готовые модули надо спрашивать у него.
Если что-то не тестируется, то и работать оно будет врядли.
Из опыта в компиляторе поставляемом с делфой могут отсутствовать фичи (наверно недоделаные/в процессе разработки), а в исходниках RTL/VCL использоваться. Вероятно потому что дешевле не править RTL/VCL лишний раз.
Соответственно компилироваться не будет.

>а какой тэг используется для подсветки паскаля?
http://skif.qrim.ru/docs/help внизу страницы

edit:
Впрочем, таки глянул на TList, тип его элемента это Pointer, а не TObject. Pointer кастуется к любому другому указателю (а объекты это указатели) автоматически
Тип элемента TObject у TObjectList, и на

var
  x: TObjectList; 
  y: TWinControl;
begin
  y := x[0];
end;

будет ругаться.

В современных делфях я использую генерики TList<> и TObjectList<>

#804
14:55, 8 ноя 2022

CD
> тип его элемента это Pointer, а не TObject
Да, точно. Видимо я при портировании поменял на TObject и забыл об этом.

CD
> В современных делфях я использую генерики TList<> и TObjectList<>
Шаблоны?

#805
15:13, 8 ноя 2022

g-cont
> По какому принципу в Dlphi осуществляется неявное приведение типов?
Pointer - это нетипизированный указатель. Еще со времен паскаля так повелось, что его всегда можно неявно привести к любому типизированному указателю.

> Здесь по смыслу нужен dynamic_cast, но компилятор, судя по всему вставляет
> static_cast и скорее всего делает это без каких-либо предупреждений.
dynamic_cast для Delphi для объектов посути то же, что и static_cast и reinterpret_cast. Т.к. в делфи нет множественного наследования, то после каста новый указатель всегда будет указывать туда же, куда и кастуемый.

#806
15:44, 8 ноя 2022

MrShoor
> Т.к. в делфи нет множественного наследования, то после каста новый указатель
> всегда будет указывать туда же, куда и кастуемый.
Но ведь можно же еще проверить иерархию на корректность.

Вот еще очень жосткая непонятка:

procedure TControl.SetAlign(Value: TAlign);
var
  OldAlign: TAlign;
begin
  if FAlign <> Value then
  begin
    OldAlign := FAlign;
    FAlign := Value;
    Anchors := AnchorAlign[Value];
    if not (csLoading in ComponentState) and (not (csDesigning in ComponentState) or
      (Parent <> nil)) and (Value <> alCustom) and (OldAlign <> alCustom) then
      if ((OldAlign in [alTop, alBottom]) = (Value in [alRight, alLeft])) and
        not (OldAlign in [alNone, alClient]) and not (Value in [alNone, alClient]) then
        SetBounds(Left, Top, Height, Width)
      else
        AdjustSize;
  end;
  RequestAlign;
end;

TAlign это обычный энумератор, т.е. не набор битовых флагов. Но его проверяют как будто это именно биты. А кое-где - на прямое соответствие значению. Как это работает?

#807
16:00, 8 ноя 2022

g-cont
> Но ведь можно же еще проверить иерархию на корректность.
Ну в делфи есть всего два каста:
myControl := TMyControl(Control);
и
myControl := Control as TMyControl;
Первый - аналогичен скажем reinterpret_cast в плюсах. Никто ничего не проверяет. Второй - проверяет иерархию, аля dynamic_cast в плюсах, и если не поддерживается, то бросает исключение. Всё.

> TAlign это обычный энумератор, т.е. не набор битовых флагов. Но его проверяют
> как будто это именно биты. А кое-где - на прямое соответствие значению. Как это
> работает?
В делфи крутая концепция энамов и множеств. Если ты пишешь:
TmyEnum = (meOne, meTwo, meSome);
то делфи под капотом сама проиндексирует (как и плюсы):
TmyEnum = (meOne = 0, meTwo = 1, meSome = 2);
Далее ты можешь объявить множество:
TmySet = set of TmyEnum;
В этом случае индексы энама будут работать как индексы битов в значениях TmySet

А вот это: [alTop, alBottom] множество типа TmySet (даже если ты не объявлял такой тип, делфи сама его неявно создаст). Ну и так как работа идет уже с множеством, то можно проверить входит ли элемент в множество с помощью оператора in

#808
(Правка: 16:24) 16:05, 8 ноя 2022

Иными словами, meOne = 0 превращается в meOne = 1<<0 как только мы начинаем их проверять в этих множествах?

Тут что-то иное. Скорее похоже, что условие, типа

if FDockSite.Align in [alTop, alBottom] then

Раскладывается в нечто подобное

if( FDockSite.Align == alTop || FDockSite.Align == alBottom )
#809
16:23, 8 ноя 2022

g-cont
> Иными словами, meOne = 0 превращается в meOne = 1<<0 как только мы начинаем их
> проверять в этих множествах?
да

Страницы: 153 54 55 5658 Следующая »
ПрограммированиеФорумОбщее