![]() |
1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!
![]() |
sheka |
![]()
Сообщение
#1
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Реализовать многоразовый вывод разных картинок на экран.
Я думаю это сделать с помощью ООП: сделать массив разнотипных объектов и потом просто вызывать отрисовку. Заголовок (Показать/Скрыть)
Тут проблемы: 1. При присваивании родителю наследника некоторые поля откидываются, т. е. это не будут полноценные объекты. 2. Сreate все таки вне цикла 3. Если делать не динамическими переменными почему-то writeln('s = ',s); строку s не выводит 4. Одним местом чувствую, что с памятью что-то не то, т. к. учитывая, что идет подгонка под родителя, то почему-то памяти выделяется как под наследника. |
![]() ![]() |
volvo |
![]()
Сообщение
#2
|
Гость ![]() |
Давай по порядку:
1) зачем ты отдельно инициализируешь p1, и только потом копируешь это значение в a[1]? Сразу, на месте, сделать нельзя? type ? 2) если у тебя есть виртуальные методы - всегда делай виртуальный деструктор. 3) Цитата При присваивании родителю наследника некоторые поля откидываются Именно поэтому и делается на указателях + полиморфная процедура:Как-то вот так (Показать/Скрыть)
Цитата Сreate все таки вне цикла Вне какого цикла? Оно и должно быть до цикла, цикл - по уже созданным с его помощью объектам... |
sheka |
![]()
Сообщение
#3
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Цитата Именно поэтому и делается на указателях + полиморфная процедура при работе с указателями памяти выделяется столько сколько нужно под целый объект, в отличии от присваивания статических объектов?Цитата если у тебя есть виртуальные методы - всегда делай виртуальный деструктор. хотя бы пустой написать, чтобы таблицу связей удалил?// удалять не забывай, чтоб потом когда функционал добавишь - утечек не было Сообщение отредактировано: sheka - 23.02.2011 14:09 |
volvo |
![]()
Сообщение
#4
|
Гость ![]() |
Цитата при работе с указателями памяти выделяется столько сколько нужно под целый объект, в отличии от присваивания статических объектов? При присваивании статических объектов Предок <- Потомок у тебя копируются только поля, существующие в предке. Все остальные - теряются, ибо места под них не было выделено (не телепат твой TFirst, чтобы знать, что у него в будущем появится потомок TSecond, а тем более, чтобы знать, какие поля он будет содержать). Зато конструктор TSecond прекрасно знает, что этот тип - потомок TFirst, и какие поля есть у потомка, и какие поля есть у него самого, сколько памяти выделить под конкретный экземпляр. Поэтому создаем объект динамически (вызовом нужного конструктора, тогда будет выделено именно столько памяти, сколько нужно для этого конкретного объекта), и передаем разыменованный указатель в полиморфную подпрограмму. А там уже забота компилятора разобраться, какой метод ты дергаешь, статический он или виртуальный, и чей именно метод будет вызван. В моем примере Draw у базового типа виртуальный - значит, вызовется Draw из того типа, который ты создавал в arr[ i ], а потом разыменовывал. Если я уберу Virtual из описания TFirst - то реально нужный мне метод уже не вызовется, отработает только пустой Draw базового класса (кстати, совершенно легальная ситуация, когда у тебя какие-то методы статические, а на каком-то этапе ты делаешь их виртуальными, и виртуальными они уже будут у всех наследников ниже по дереву. Обратное невозможно, т.е., изначально виртуальный метод не может в одном из потомков стать статическим).Цитата хотя бы пустой написать, чтобы таблицу связей удалил? Хотя бы пустой напиши (для каждого типа в иерархии). Чтобы объект нормально освободил занимаемую память. |
sheka |
![]()
Сообщение
#5
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Пока получается как-то так:
Главная программа (Показать/Скрыть)
unit UBase; (Показать/Скрыть)
unit UCircle; (Показать/Скрыть)
unit ULine; (Показать/Скрыть)
Подскажите что не так, как может можно сделать красивее выбор ввода вручную или из файла? Прикрепленные файлы ![]() |
volvo |
![]()
Сообщение
#6
|
Гость ![]() |
Во-первых, есть перегрузка функций (я про конструктор), во-вторых - значения по умолчанию. Совмещаем и получаем:
ULine.pas {$mode objfpc}, то же самое делаешь для UCircle.pas, и потом вызываешь: InitGraph(gd,gm,''); |
sheka |
![]()
Сообщение
#7
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Вернемся к тем же баранам:
![]() В ULetterBox - массив объектов, наследников TShape. При заполнении этого массива TBar(TShape) не передаются размеры - поля, описанные в TBar. Следовательно, на экран вместо прямоугольников выводятся точки. |
volvo |
![]()
Сообщение
#8
|
Гость ![]() |
Не понял, что именно у тебя не происходит? Ты там что-то много наворотил, можешь конкретно названия файлов и номера строк указать, в которых делается не то, что ты задумывал (и, заодно, описать что именно ты задумывал, неплохо было бы).
А вообще - опиши задачу полностью. Есть стойкое ощущение, что ты изобретаешь какой-то грандиозный велосипед. Может, это делается гораздо проще? |
sheka |
![]()
Сообщение
#9
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Задание: сделать игру "Виселица". Учитывая, что тупо выбор кейсом нажатой клавиши + выбор кейсом отрисовки ошибки есть дело одного часа + это не интересно, решил выучить ООП.
![]() Все аналогично решению в посте №2, только почему-то не работает: В объекте ТLetterBox(модуль ULetterBox) есть поле-массив PLetter объектов типа TShape (27строка). При создании этого ТLetterBox создаются элементы этого массива (93) типа TLetterShape, который = TBar. Заполнение этого массива (42) происходит так: есть доп. переменная PSample тех же типов, что и элементы PLetter (18,154). Из файла инфо записывается сначала в нее, а потом уже копируется во все элементы массива. Ошибка в том, что элементы массива типа TShape, а создаются с типом TBar(TShape) и таким образом не передаются размеры - поле BarDim, описанные в TBar (в UBar 19стр). Следовательно, на экран вместо прямоугольников выводятся точки. Если заменить тип элементов массива PLetter 12строка в модуле ULetterBox с TShape на TBar - то все замечательно работает. |
volvo |
![]()
Сообщение
#10
|
Гость ![]() |
Цитата Ошибка в том, что элементы массива типа TShape, а создаются с типом TBar(TShape) и таким образом не передаются размеры Ты действительно считаешь, что поведениеPLetter^[ i ]^ := PSample^;, где PLetter[ i ] - типа PTShape, а PSample - создан как PSample := new(PTLetterShape, Create);, то есть, фактически, ты присваиваешь TShape <- TBar, разумеется, все отсутствующие в TShape поля перенесены гарантированно не будут, по правилам присваивания предку значения-потомка - это ошибка? Это ошибка, только чья? А между тем, если сделать два вот таких простых движения: 1) описание типов type 2) метод TLetterBox.LettersLoadFromFile(const FileName: string); for i := 1 to ColCount*(RowCount-1) do, то все заведется как положено, и будет рисоваться рамка. Просто изменение типа PSample ничего не даст. Объяснить причину сможешь? P.S. На самом деле первое движение можно не делать, а второе сделать чуть более хитро: PTLetterShape(PLetter^[i])^ := PTLetterShape(PSample)^;, это тоже должно сработать, лень проверять ![]() |
sheka |
![]()
Сообщение
#11
|
![]() Я. ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 809 Пол: Мужской Реальное имя: Саша Репутация: ![]() ![]() ![]() |
Работает. Не даст, потому что
Цитата фактически, ты присваиваешь TShape <- TBar, разумеется, все отсутствующие в TShape поля перенесены гарантированно не будут, по правилам присваивания предку значения-потомка |
![]() ![]() |
![]() |
Текстовая версия | 4.07.2025 18:51 |