Помощь - Поиск - Пользователи - Календарь
Полная версия: Задачи на знание ООП
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Страницы: 1, 2, 3
volvo
А ты - по ссылке, которую я давал раньше, там все написано smile.gif
Ничего к сказанному там я добавить не могу...
Bokul
Так?

type
PT = ^T;
T = object
constructor create;
destructor done;{добавляем деструктор}
end;




destructor T.done;{который ничего не делает}
begin
end;




procedure TArr.count_each(const p: PT);
var i, count: integer;
begin
count := 0;
for i := 1 to maxSize do
if (arr[i]<>nil) and (typeof(arr[i]^) = typeof(p^))
then inc(count);
writeln('count = ', count);
dispose(p,done);{------------свобождаем память}
end;



var
obj_int: PTint;
obj_float:PTfloat;
any_arr: TArr;
mem:longint;
begin
clrscr;
mem:=memavail;{замеряем память до начала свалки}
any_arr.init;
obj_int := new(PTint,create);
obj_int^.value := 3;
any_arr.set_index(1, obj_int);
obj_float := new(PTfloat,create);
obj_float^.value := 3.5;
any_arr.set_index(2, obj_float);
any_arr.count_each(new(PTfloat,create));
dispose(obj_float,done);{чистим за собой}
dispose(obj_int,done);{и это тоже}
writeln('Difference : ',mem-memavail);{вроде так как и было...}
readln;
end.


Полный код:
volvo
Цитата
Так?
no1.gif

Добавление 3-х строк в те участки, в которые я показал - результат в аттаче... Не все утечки убраны... blum.gif
Bokul
Что ж там за строки blink.gif У меня максимальная утечка была 16 байт, у тебя -320 mega_chok.gif
volvo
Bokul, в моем скриншоте содержится скрытая подсказка smile.gif
Bokul
Все, сдаюсь... Не вижу, где убегают драгоценные байты... Идей нету, может только еще один деструктор для TArr сделать, но это уже гадание... так что прошу показать правильное решение. smile.gif
volvo
Цитата
Не вижу, где убегают драгоценные байты...
Хорошо... Подсказываю. Вот тут:

procedure TArr.set_index(i: integer; p: PT);
begin if i <= maxSize then arr[i] := p; end;

Что будет, например, если я запишу 4 раза подряд в первую ячейку заново инициализированный объект? Я имею в виду, что будет с тем объектом, адрес которого там был записан РАНЬШЕ? Он останется висеть в памяти, а указатель на него ты потеряешь smile.gif

Теперь понятно, что надо поправить?
Bokul
Аааа... Мелькала такая мысль, ну только я ее сразу почему-то отбросил.
Цитата
Теперь понятно, что надо поправить?

Ага yes2.gif Но я вижу три способа:
1 удалять с кучи прежний объект
2 не допускать этого
3 самому назначать индексы
Цитата
Я имею в виду, что будет с тем объектом, адрес которого там был записан РАНЬШЕ?

но смотря как передавать... если инициализировать объект прямо в методе
any_arr.set_index(1,new(PTfloat,create));

то действительно потеряем, если же через известный указатель, то не вижу никаких проблем.
volvo
Цитата
если же через известный указатель, то не вижу никаких проблем.
Да? Зато я вижу: допустим, тебе надо создать кортеж из 500 элементов... Будешь создавать 500 переменных-указателей? Тогда зачем, извини, тебе кортеж... Работать-то будешь все равно через одну (максимум - две, потому что есть 2 разных типа реальных объектов, которые ты можешь создать) переменные. И все равно потеряешь старое значение при инициализации нового экземпляра...

Цитата
я вижу три способа:
Если можно - решения для всех трех - в студию smile.gif
Bokul
Цитата
Если можно - решения для всех трех - в студию

Сделаем, но только через часиков 10 - сейчас спать, а завтра в школу не идти smile.gif

P.S. Я конечно понимаю, что достал уже, но я так и не понял, что Паскаль делает с этим неизвестным указателем wub.gif
Bokul
Цитата
1 удалять с кучи прежний объект


constructor TArr.init;{добавим некую полезную нагрузку в конструктор}
var i:byte;
begin
for i:=1 to maxSize do {обnilим все элементы}
arr[i]:=nil;
end;



procedure TArr.set_index(i: integer; const p: PT);
begin
if i<= maxSize then
begin
if arr[i]=nil then
arr[i]:=p
else
begin
dispose(arr[i],done);
arr[i]:=p;
end;
end;
end;


Нажмите для просмотра прикрепленного файла

Цитата
2 не допускать этого


function TArr.set_index(i: integer; const p: PT):boolean; {сделаем функцию вместо процедуры
true - все нормально
false - наоборот}
begin
if i<= maxSize then
if arr[i]=nil then
begin
arr[i]:=p;
set_index:=true;
end
else
set_index:=false;
end;


Нажмите для просмотра прикрепленного файла

Цитата
3 самому назначать индексы


type
TArr = object
arr: array[1 .. maxSize] of PT;
num:byte;{сколько объектов уже было добавлено}
procedure set_index(const p: PT);{i нам больше не понадобится}
end;




constructor TArr.init;
var i:byte;
begin
num:=0;{!!!!!!!!!!!!!!!!!}
for i:=1 to maxSize do
arr[i]:=nil;
end;



procedure TArr.set_index(const p: PT);
begin
if num< maxSize then
begin
inc(num);
arr[num]:=p;
end;
end;


Нажмите для просмотра прикрепленного файла

PS Только что заметил: по времени вышло почти 10 часов, как и предсказывал, хотя я и не подстраивался smile.gif
volvo
Первый вариант не убирает утечки: добавление тех же самых 3-х строк, что и раньше:
Нажмите для просмотра прикрепленного файла

Второй и третий не тестировал ...
Bokul
Я не понимаю почему там не возникает ошибки.
  
obj_int := new(PTint,create);
obj_int^.value := 3;
any_arr.set_index(1, obj_int);


Сейчас obj_int и первый элемент массива any_arr.arr указывают на один и тот же объект в кучи.


any_arr.set_index(1, obj_float);


Теперь я хочу поставить первым элементом указатель на другой объект.
		
begin
dispose(arr[i],done);
arr[i]:=p;
end;


Так как первый элемент не равнялся nil, то выполнение any_arr.set_index приведет к выполнению этого куска кода, в котором мы освобождаем память, выделенную под Tint, но один указатель, связанный с этим участком памяти, у нас остался - obj_int.
Почему не возникает ошибки сдесь:
dispose(obj_int,done);

? Эта ж память уже не с чем не связанна...
volvo
Цитата
Я не понимаю почему там не возникает ошибки.
Это ты как определил? Я бы выразился по-другому: Turbo Pascal не показывает тебе, что там есть ошибка... Попробуй тот же код (закомментировав MemAvail) прогнать в FPC smile.gif
Bokul
Error 210
Цитата

With range-checking on, you made a call to an
object's virtual method, before the object
had been initialized via a constructor call.

Почему Turbo Pascal не видит эту ошибку? Что он делает? Еще раз освобождает эту память? А если она уже была зарезервированна для другого объекта или переменной?
А вот в таком случае (см. атач) получаем RunTime Error 204. Какая разница? Почему в данном варианте он видит, а там - нет?
Bokul
Извиняюсь, не увидел вопроса
Цитата
Это ты как определил?

После столько часов медитации над кодом все видно yes2.gif . Fpc не запускал.
Bokul
Надо сделать деструктор объекта T виртуальным, так как для правильной очистки полиморфических объектов с памяти надо знать их размер, а виртуальный деструктор это обеспечит. Естественно у наследников надо тоже сделать деструкторы виртуальными. Правильно?????
Bokul
Цитата
Надо сделать деструктор объекта T виртуальным, так как для правильной очистки полиморфических объектов с памяти надо знать их размер, а виртуальный деструктор это обеспечит. Естественно у наследников надо тоже сделать деструкторы виртуальными. Правильно?????

Или уже никто не заглядывает в эту тему?
volvo
Ну, так ты программу-то приаттачь со всеми изменениями, тогда и посмотрим, остаются утечки или нет smile.gif Что же толку, если я сделаю те изменения, которые нужны?
Bokul
Вот:
volvo
В принципе, почти правильно... Но нужно еще кое-что добавить, потому что программа еще пропускает, например... Ну, вот результат:
Bokul
А утечек нету?

А с 210 я воюю уже давно, даже догадываюсь что ты поменял yes2.gif
any_arr.count_each(new(PTfloat,create));

вместо new(PTfloat,create) поставил что-то наподобие obj_float... Так?
Бороться не знаю как... Подскажешь?
Bokul
Продолжаю ставить вопросы на которые никто не отвечает dry.gif
Можно ли как-то программно отличить any_arr.count_each(new(PTfloat,create) ) от any_arr.count_each(obj_float )?
volvo
Отвечаю... Естественно, вопросом на вопрос: "А зачем?"

Смысл этого привести сможешь? Что тебе даст, если ты это определишь? Все равно, у тебя (почти всегда) в count_each будет передан указатель на объект. Вот и работай с ним... Какая тебе (а тем более, твоей функции count_each) разница, сконструирована инициализация объекта прямо на месте, или передан указатель, уже использованный в программе? Это что-то меняет? Значит, неправильно спроектирована программа... Исправляй так, чтобы работало независимо от способа передачи параметров... blum.gif
Bokul
Цитата
Значит, неправильно спроектирована программа...

Полностью согласен. smile.gif
Цитата
Какая тебе (а тем более, твоей функции count_each) разница, сконструирована инициализация объекта прямо на месте, или передан указатель, уже использованный в программе?

А как освободить с памяти объект на который нет указателя? Вот тебе и разница... smile.gif

Вот еще вариант, мне кажется, что тоже не правильно, но идея должна быть такой, т.е. передавать в метод не указатель, а тип.
volvo
Цитата
А как освободить с памяти объект на который нет указателя?
А вот с этого места, пожалуйста, поподробнее... То есть, ты считаешь, что вот эта программа:
type
pT = ^T;
T = object
value: integer;

constructor init(x: integer);
procedure print; virtual;
end;

constructor T.init(x: integer);
begin value := X; end;
procedure T.print;
begin writeln(value); end;


procedure print_me(const p: pT);
begin
p^.print;
end;

begin
print_me(new(pT, init(20)));
print_me(new(pT, init(30)));
print_me(new(pT, init(40)));
end.
не напечатает ничего? Как же она может напечатать, если я передаю (да еще и константно) указатель на объект, который НЕ существует? Вынужден тебя огорчить, она будет работать... Объясни тогда, почему, если НЕТ указателя?

Цитата
Полностью согласен.
Ха... А ты что думал, я дам программку, в которой надо изменить 2 символа и она будет работать, как положено? Нет уж... no1.gif
Bokul
В общем я имел ввиду объект с потерянным на него указателем, но не страшно, развития вопроса мне нравится... smile.gif
Цитата
Как же она может напечатать, если я передаю (да еще и константно) указатель на объект, который НЕ существует?

Что, он действительно не существует? blink.gif Судя по изменению памяти я бы этого не сказал...
Цитата
Объясни тогда, почему, если НЕТ указателя?

Цитата
procedure print_me(const p: pT);

А что же тогда такое p?
volvo
Цитата
Что, он действительно не существует?
А теперь я тебя спрошу:
procedure TArr.count_each(const p: PT);
var i, count: integer;
begin
count := 0;
for i := 1 to num do
if (typeof(arr[i]^) = typeof(p^))
then inc(count);
writeln('count = ', count);
dispose(p,done);
end;

...
any_arr.count_each( ??? );
Что должно быть на месте вопросов, чтобы внутри count_each произошла Run-Time ошибка 210 ? smile.gif И где именно она может произойти (желательно показать строчку внутри процедуры, и сказать, ЧТО эту ошибку может вызвать)...
Bokul
Цитата
И где именно она может произойти

Так как 210 ошибка возникает при обращению к виртуальному методу не инициализированного объекта, а единственный используемый метод это done, то следовательно такая ошибка может возникнуть только здесь -
Цитата
dispose(p,done);

Цитата
Что должно быть на месте вопросов, чтобы внутри count_each произошла Run-Time ошибка 210 ?

Указатель на не инициализированный объект, правда в таком случае ошибка произойдет раньше...
volvo
Ты сам себе противоречишь, тебе не кажется? Ты покажи такой ответ, которого можно добиться... То есть, чтобы ошибка была предсказуемой... Твой предыдущий пост не отвечает на поставленный вопрос, ты вводишь сам себя в заблуждение (так ошибка произойдет на показанной тобой строке, или раньше?) Вот я сейчас могу показать, что надо сделать, чтобы произошла именно ошибка №210, а не немедленное закрытие программы, "неправильная инструкция" или еще что-то в этом роде... Следовательно, я смогу и избежать этой ошибки... Пока ты не научишься ошибки предсказывать - об их исправлении не может быть и речи blum.gif
Bokul
Цитата
Указатель на не инициализированный объект, правда в таком случае ошибка произойдет раньше...

Дамм, надо отвыкать использовать универсальное местоимение ... ... smile.gif
Дело в том, что, если мы передадим в этот метод объект без инициализированной VMT, то ошибка этапа компиляции возникнет тут :
typeof(p^)


Цитата
Ты покажи такой ответ, которого можно добиться...


var
obj_int: PTint;
p:pointer;
begin
obj_int := new(PTint,create);
p:=obj_int;
any_arr.count_each(p);
end.


Цитата
Вот я сейчас могу показать, что надо сделать, чтобы произошла именно ошибка №210, а не немедленное закрытие программы, "неправильная инструкция" или еще что-то в этом роде.

Если приведенный выше вариант не правильный, покажи... smile.gif
volvo
Цитата
ошибка этапа компиляции возникнет тут :
Правда? Даже nil не даст тебе там ошибку... Тем более на этапе компиляции... Достаточно, что тип формального параметра МОЖЕТ содержать указатель на VMT - это гарантирует успешную компиляцию...

Вот мой вариант генерации ошибки 210:
any_arr.count_each(nil);

?
Bokul
Цитата
Достаточно, что тип формального параметра МОЖЕТ содержать указатель на VMT - это гарантирует успешную компиляцию...

А существование VMT, гарантирует существование у объекта конструктора, деструктора или хотя бы одного виртуального метода?

Цитата
Вот мой вариант генерации ошибки 210:

TP вылетает, а FreePascal показывает 216-ую... Или это уже как следствие? При отладки в TP, как можна понять, что это 210-ая,? Она же "фатальная"?

А мой вариант не правильный?
volvo
smile.gif Кстати, я нашел у тебя еще кое-что не совсем корректное... Смотри:

function TArr.set_index(const p: PT):boolean;
begin
inc(num);
if num<= maxSize then
begin
arr[num]:=p;
set_index:=true;
end
else
begin
dec(num);
dispose(p,done);
set_index:=false;
end;
end;
- полностью твой код, у меня этого просто не было... А теперь представь, что мне надо первые 10 элементов установить в значение 3.5 - неужели для этого я должен инициализировать переменную 10 раз... Я сделал так:
  obj_float := new(PTfloat,create);
obj_float^.value := 3.5;
for i:=1 to 10 do
begin
if obj_float <> nil then { <--- Вот эту проверку, кстати, пользователь, делать не должен ... }
any_arr.set_index(obj_float);
end;
и что я получу, догадайся?

(а проверку, которую я показал делать пользователю класса действительно не совсем корректно, хотя даже это не помогло...)

Цитата
При отладки в TP, как можна понять, что это 210-ая,? Она же "фатальная"?
У меня в верхней строке экрана сообщается, какая ошибка произошла, ничего никуда не вылетает...

Цитата
А существование VMT, гарантирует существование у объекта конструктора, деструктора или хотя бы одного виртуального метода?
Существование VMT гарантируется вызовом конструктора. А наличие деструктора и виртуальных методов (при существовании VMT) - это уже проблема программиста... Они могут быть, а могут не быть - это синтаксисом не оговорено...

С другой стороны, даже наличие у объекта 10 виртуальных методов тебе ничего не даст, если ты НЕ сконструировал экземпляр как положено, т.е. можно сказать так: наличие правильной VMT не гарантируется ничем, кроме вызова конструктора... А дело-то все в том, что TypeOf во время компиляции не может проверить правильность таблиц виртуальных методов, ибо эти самые таблицы только в RunTime создаются...
Bokul
Цитата
и что я получу, догадайся?

Большую толстую ошибку smile.gif
Получаем 10 указателей на один и тот же объект, что есть не очень хорошо, так как потом мы попытаемся их все освободить из памяти при помощи виртуального деструктора, но после первого "освобождения", нам останется 9 указателей на объект без VMT, что при последующим вызове виртуального done вызовет ошибку 210.
Цитата
а проверку, которую я показал делать пользователю класса действительно не совсем корректно, хотя даже это не помогло...

Все понял. Мне вообще интересует вопрос о том, что должен знать и не знать объект.
Цитата
А дело-то все в том, что TypeOf во время компиляции не может проверить правильность таблиц виртуальных методов

Я тут уже задавал вопрос, но так и не услышал ответа: что на самом деле делает TypeOf? Возвращает значения поля виртуальных объектов у объекта?
А как она может проверить правильность этих таблиц? Ведь вся инфа об объекте хранится именно там?
Цитата
наличие правильной VMT не гарантируется ничем, кроме вызова конструктора...

Я так и не понял (вернее опять запутался) что делает конструктор. Я думал, что он заполняет ПВМ (поле виртуальных методов), а в построении таблиц он не участвует.

Вопрос Из чего состоит размер объекта? Только из его полей + , при условии существования конструктора, 4 байтов для ПВМ?
volvo
Цитата
Я так и не понял (вернее опять запутался) что делает конструктор.

Цитата(http://sizov.boom.ru/books/turbo6/tpash.htm)
Как упомянуто ранее, констрактор объектного типа содержит специальный код, который сохраняет смещение VMT объектного типа в инициализируемом экземпляре.


Цитата
Я думал, что он заполняет ПВМ (поле виртуальных методов), а в построении таблиц он не участвует.
Я где-то сказал, что он участвует в построении таблиц? blink.gif Я сказал, что до тех пор, пока ты не вызовешь конструктор, с VMT правильно работать не получится, следовательно ни на SizeOf ни на TypeOf полагаться нельзя, ибо они как раз работают с тем адресом, который этим самым конструктором заносится в поле экземпляра объекта...


Цитата
Из чего состоит размер объекта? Только из его полей + , при условии существования конструктора, 4 байтов для ПВМ?

Во-первых, я уже давал тебе ссылку, а во-вторых - не 4-х а 2-х байтов (в поле хранится только 16-битное смещение, ибо компилятору, а следовательно и программе, прекрасно известно, что VMT хранится в сегменте данных, так зачем за собой таскать еще 2 лишних байта? Помнишь мою программу с елкой? На сегодняшний день в ней - работа над программой продолжается - до 3000 объектов с виртуальными функциями одновременно висят в памяти, если каждый из них будет захватывать 2 "лишних" байта - то 6К у тебя вычеркнуто из размера кучи, а она не такая уж и большая, чтобы так вольно с ней обращаться...)

Цитата
Мне вообще интересует вопрос о том, что должен знать и не знать объект.
Объект должен знать ровно столько, сколько ему необходимо для того, чтобы корректно работать... В частности, информация, как был создан указатель на объект, передаваемый ему в качестве параметра (операция @, примененная к статическому объекту, взятие Addr от типизированной константы объектного типа, или конструирование прямо "on the fly" через New) - совершенно не должна его интересовать... С любым из этих случаев работа должна производиться одинаково, для этого у тебя и объявлен тип формального параметра...

Цитата
что на самом деле делает TypeOf? Возвращает значения поля виртуальных объектов у объекта?
Возвращает нормализованный указатель на VMT для заданного типа/экземпляра (т.о., если эти указатели равны, то экземпляры принадлежат к одному и тому же типу)...
Цитата
Ведь вся инфа об объекте хранится именно там?
Там хранятся только адреса виртуальных процедур/функций, это еще не ВСЯ информация, а только ее часть.
Bokul
Спасибо, теоретическая часть укрепилась. good.gif
То как там по поводу
Цитата
Большой толстой ошибки:
Получаем 10 указателей на один и тот же объект, что есть не очень хорошо, так как потом мы попытаемся их все освободить из памяти при помощи виртуального деструктора, но после первого "освобождения", нам останется 9 указателей на объект без VMT, что при последующим вызове виртуального done вызовет ошибку 210.

Правильно?
volvo
Цитата
Правильно?
Не совсем... В том фрагменте, который я тебе привел (пост №84), происходит следующее: я получил указатель на объект. Здесь все по правилам... Дальше я хочу просто один и тот же указатель 10 раз передать в функцию, чтобы 10 последовательных ячеек были заполнены одинаковым значением.. И что? Твоя реализация мне этого не позволяет, потому что после первого же Dispose указатель становится, скажем так, невалидным (вообще-то это определение из С++, но очень оно мне нравится, я использую его и здесь)... Хотя указатель передается в функцию через спецификатор Const, все-же Dispose к нему применяется, а значит, удаляется связь экземпляра с VMT, что перечеркивает возможность дальнейшего использования как этого объекта, так и указателя на него...

А надо бы такое (я про использование одного указателя для нескольких ячеек) позволять... Что для этого придется сделать? Есть мысли?

Кстати, еще один вопрос, по ходу действия, у меня к тебе (ибо отвечаешь и интересуешься этой темой только ты, остальные видимо, знают все в совершенстве) : допустим, есть фрагмент кода:

type
pT = ^T;
T = object
...
end;

procedure X(const the_pointer: pT);
begin
if assigned(the_pointer) then writeln('not assigned');
end;

var
p: ^T;
...
X( {что-то} )
...
Можно ли добиться того, чтобы при каких-то условиях было выведено сообщение "not assigned", и если ответ = "да", то перечисли все способы, которые ты можешь себе представить для этого (ничего не меняя внутри самой процедуры X, только снаружи), а если "нет" - то почему? smile.gif
Bokul
Цитата
procedure X(const the_pointer: pT);

А сначала ведь был Var wink.gif
Цитата
Хотя указатель передается в функцию через спецификатор Const, все-же Dispose к нему применяется, а значит, удаляется связь экземпляра с VMT

В каком смысле удаляется? wub.gif Я понимаю, что память, ранее зарезервированная под объект, уже больше не связанна с указателем на него (объект), и что в любое время она может быть переписана, но ведь ПВМ все-равно продолжает указывать на VMT объекта.
Цитата
А надо бы такое (я про использование одного указателя для нескольких ячеек) позволять... Что для этого придется сделать? Есть мысли?

Сделать только один указатель связанный с самим объектом, остальные будут связанные с ним... wacko.gif В общем над этим вопросом думаю 61 поста, нормальных идей не было...
Цитата
Можно ли добиться того, чтобы при каких-то условиях было выведено сообщение "not assigned", и если ответ = "да", то перечисли все способы, которые ты можешь себе представить для этого (ничего не меняя внутри самой процедуры X, только снаружи), а если "нет" - то почему?

if not('да') and not('не') then
writeln('не знаю ')
Bokul
Цитата
Можно ли добиться того, чтобы при каких-то условиях было выведено сообщение "not assigned", и если ответ = "да", то перечисли все способы, которые ты можешь себе представить для этого (ничего не меняя внутри самой процедуры X, только снаружи), а если "нет" - то почему?

Ха, красиво! good.gif Я сначала перепутал как действует assigned, но ничего, разобрался. Не знаю, можно ли было использовать компилятор, но я использовал, в следующий раз оговаривай, пожалуйста, этот вопрос. smile.gif

И собственно ответ:
p:^T

этот указатель ссылается на место в куче, где размещены поля объекта T, а значит, если их нету - то й указатель будет nil-овым smile.gif . Выходит, что у нас есть две возможности обеспечить работу для p:
1 Добавить в объект T любое поле.
2 Создать ПВТ.
Вот их реализация:
Цитата
1 Добавить в объект T любое поле.


type
T = object
b:byte;
end;


2 Создать ПВТ.

Выбираем один из 3 способов:
через конструктор:

type
T = object
constructor init;
end;

constructor t.init;
begin end;



через деструктор:

type
T = object
destructor done;
end;

destructor t.done;;
begin end;



и виртуальный метод:

type
T = object
procedure VirtualMethod; virtual;
end;

procedure T.VirtualMethod;
begin end;



volvo
Я не спрашивал, как обеспечить то, что P будет работать... Я спросил - может ли процедура напечатать сообщение...
Bokul
Цитата
Я не спрашивал, как обеспечить то, что P будет работать... Я спросил - может ли процедура напечатать сообщение...

Может, забыл дописать еще пару строчек.
Выбираем один из методов создания поля (описанных выше), а потом -

var
p: ^T;
begin
new(p);
X(p);
end.

Алена
Пока volvo не будет - я продолжу за него, хорошо?

Вопрос немного меняется: пост №88 - процедуру изменяем вот так:
procedure X(const the_pointer: pT);
begin
if NOT assigned(the_pointer) then writeln('not assigned');
end;

Задача - не используя в программе переменных типа pT (за исключением формального параметра процедуры) заставить эту самую процедуру напечатать "not assigned"... Если есть несколько способов сделать это - приведите их ВСЕ (ответы принимаются в виде работоспособного кода, а не просто отдельными вставками "а если сделать то-то и то-то")
Bokul
Цитата
Пока volvo не будет - я продолжу за него, хорошо?

Если он и не против, то почему бы и нет smile.gif
Цитата
Вопрос немного меняется

Подожди. То, что я по тому вопросу написал, правильно?
Алена
По тому вопросу - правильно, но там он просто ошибся, и не поставил сразу NOT в процедуру... Весь смысл был как раз в том, чтобы сделать такой вариант задания, который привела я...
Bokul
Цитата
По тому вопросу - правильно, но там он просто ошибся, и не поставил сразу NOT в процедуру...

Откуда такая увереность? wink.gif
Цитата
Весь смысл был как раз в том, чтобы сделать такой вариант задания, который привела я...

Не знаю, то показалось сложнее

type
pT = ^T;
T = object
end;

procedure X(const the_pointer: pT);
begin
if not(assigned(the_pointer)) then writeln('not assigned');
end;

var
p: ^T;
begin
X(nil);
end.


Алена
Еще варианты будут?

Если нет, то я добавляю еще одно ограничение - на использование nil ... Это слово встречаться в программе не должно (равно, как и приведение к нему, вроде X(Pointer(0)))

Your turn smile.gif
Bokul
Цитата

Еще варианты будут?
Если нет, то я добавляю еще одно ограничение

lol.gif lol.gif lol.gif
Цитата
Your turn

d'accord smile.gif
Паскаль, вроде, сам по-началу делает все указатели равным nil...

type
pT = ^T;
T = object
end;

procedure X(const the_pointer: pT);
begin
if the_pointer=nil then writeln('not assigned');
end;

var
p: ^T;
begin
X(p);
readln;
end.


Алена
А внимательно прочитать предыдущие посты - никак?

Цитата
Задача - не используя в программе переменных типа pT (за исключением формального параметра процедуры)


Я надеюсь, не надо говорить, что ^T и pT это одно и то же? Иначе никакие задачи давать просто невозможно, ибо надо давать также 20 страниц описаний, что считается нарушением, а что нет... Этого я делать не буду...

Не принято ... Кроме того, изначальное присвоение nil - это компиляторозависимо, и полагаться на это просто опасно...
Bokul
Вот:

type
pT=^t;
T=object
constructor init;
end;
constructor T.init;
begin end;

procedure X(const the_pointer:pT);
begin
if the_pointer=nil then writeln('not assigned');
end;

var p:pointer;
ob:t;
begin
p:=@p;{свяжем p с любым адресом}
getmem(p,sizeof(ob));{p:=nil}
x(p);
readln;
end.


Честно говоря не понимаю почему так. wacko.gif Если на месте ob поставить t, ничего не получится. Почему?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.