Пример чисто виртуальный, никакой полезной нагрузки для практики не несёт вообще... но однако он основан на элементарщине в ООП... не понимаю почему почему FPC это не хавает... хотя Си такую вещь успешно исполняет, где у Паскаля - segmentation fail...
итак... из теории мы знаем, что методы живут отдельно от данных... в FPC почему-то не так...
вот исходный код на C++:
- Код: Выделить всё
- #include <iostream>
 class Foo
 {
 public:
 void foo()
 {
 std::cout << "hello world" << std::endl;
 }
 };
 
 int main()
 {
 Foo& foo = *(Foo*)NULL;
 foo.foo();
 }
если кто ничерта не въезжает в подобные сишные приёмы...
с упрощением main() будет:
- Код: Выделить всё
- int main()
 {
 Foo *foo = (Foo*)0;
 foo->foo();
 }
здесь, эта вот хитрая конструкция "Foo *foo = (Foo*)0;" происходит от того, что в Си нет автоматического преобразования из нетипизированного указателя в типизированный, по сути это просто Foo * foo = 0, но писать надо так...
и вот это в C++ собирается и работает... написать аналог в FPC мне конечно удалось... и он собирается... но не работает...
это меня и озадачило... получается, что FPC не умеет отделять мух от котлет - методы от данных...
вот мой вариант перевода:
- Код: Выделить всё
- {$mode objfpc}
 type
 Foo = class
 public
 procedure foo;
 end;
 procedure Foo.foo;
 begin
 Writeln('test');
 end;
 var
 _foo:^Foo;
 begin
 _foo:=nil;
 _foo^.foo;
 end.
вот, более аккуратный:
- Код: Выделить всё
- PFoo = ^TFoo;
 TFoo = class
 public
 procedure foo;
 end;
 procedure TFoo.foo;
 begin
 writeln('Hello world!!!');
 end;
 var
 p: pointer;
 a: PFoo;
 begin
 p := nil;
 a := p;
 a^.foo;
 end.
почему это не работает??? где ошибка? с точки зрения основ ООП всё сделано верно!
Похоже на то, что паскаль в этот код другую семантику вкладывает. Непонятно почему
Разыменование pointer^.data понятно является косвенной адресацией относительно адреса pointer. Но pointer^.method() семантически означает другое. Он говорит о том, что нужно взять method() относящийся к типу указателя pointer и передать ему данные по указателю pointer. И почему это не работает - не знаю. Помогите, кто чем поможет)
ещё более точно:
Операция "точка" является перегруженной и имеет совсем разный смысл при обращении к полям и методам объекта класса. Именно в этом и суть данного примера в Си++ - отличная ловушка для экзаменуемых.
Начнём с того, как они понимают операцию "точка" в только что описанном контексте.
ВЕДЬ "type_pointer^.data" и "type_pointer^.method()" - это совсем разная семантика и совершенно разная работа с указателями внутри реализации!!!
Что нужно сделать чтобы получить адрес data? Надо выполнить косвенную адресацию относительно type_pointer
А что нужно сделать чтобы получить адрес метода method()?
!!! Для этого не нужно выполнять косвенную адресацию относительно type_pointer!!!
Для этого нужно знать тип указателя, чтобы определиться с пространством имен, где надо искать адрес функции method()!!!
почему это не работает?







