классы, методы, свойства и объекты.
Участников: 4
Страница 1 из 1
классы, методы, свойства и объекты.
Глава посвящена созданию класса. Как его объявлять, как создавать свойства и методы.
введение
классы во FreeBasic есть!Тем, кому нужна теоретическая подготовка, то читать теорию ооп
Только выглядит это очень непривычно, по сравнению с некоторыми другими языками.
Дальше я буду рассказывать именно о реализации объектной модели в FreeBasic.
В принципе, бейсиковские типы данных, очень похожи на объекты, синтаксически.
Ну вот от сюда видимо исходили.
Класс объявляет конструкция type
А внутри неё можно делать свойства. Это как по старому, с пользовательскими типами данных.
Но можно декларировать и методы, в качестве которых используются процедуры (sub) и функции (function). А вот здесь и начинаются необычности.
методы
Сама функция или процедура может находиться где угодно, но её имя должно начинаться с имени класса и точки.
Да, это весьма непривычно.
В C++ кажется что-то похожее, но там всё берётся в блок с ключевым словом class, а здесь такого нет. Возможно в будущих версиях ситуация измениться, но не будем загадывать.
активные свойства
Теперь об активных свойствах. Это вообще уникальное явление, которого я кроме бэйсика не где не встречал. Под свойствами я подразумеваю конструкцию property.
Это даже больше соответствует концепции ооп, чем в других языках. Там программисты использовали методы get и set.
Те кто знаком с visual basic знают property. Только они использовали ключевые слова get и let. А в FreeBasic они опущены. Это логично, поскольку по аргументам и так понятно, что к чему.
Для тех, кто не знает, рассказываю подробнее.
Конструкция property (свойство) - это функции которые принимают и возвращают свойства класса. Их должно быть две (обязательно иначе мой fb ругался). Причём
с одинаковыми именами.
Объекты
Объект это переменная, которая содержит экземпляр класса.
Вот и всё. У нас уже есть объект a_object.
Ну а дальше поступаем с ним как хотим. Объект, являеться всего-лишь переменной.
Используя объект, мы можем обращаться к свойствам и методам экземпляра класса.
Как мы можем видеть, всё так, как было с пользовательским типом данных.
ключевое слово this
внутри класса, переодически приходится обращаться к текущему экземпляру. Ключевое слово this нужно писать вместо имени класса.
Это копия объекта внутри класса.
конструкторы и деструкторы
Помню, долго я искал их в vb6, запрятаны они были в странные слова, кои повторять нехочеться. А тут всё просто
constructor и destructor. Использовать нужно вместо sub.
Здорово? Вот бы везде так чётко.
Кажется конструкторов и деструкторов может быть несколько, но я ещё не проверял.
объекты по ссылке
Объекты по ссылке или указателю, мне показались более удобным решением, чем обычные. Чтобы понимать, о чём дальше пойдёт реч, ознакомьтесь с главой указатели (pointer).
Давайте познакомимся с двумя функциями.
new - создание объекта в памяти. Возвращает указатель, на объект.
Такое объявление совершенно правильно и логично, хоть и выглядит громоздко. Возможно в будущих версиях всё измениться.
Функция new создаёт в памяти экземпляр указанного класса. Срабатывает конструктор, если таковой есть. А в указатель записываеться указатель на объект.
delete - удаляет объект из памяти. В качестве параметра передаёться указатель на объект.
Память высвобождаеться, но перед этим запускаеться и отрабатывает деструктор.
Обращаться к методам и свойствам класса нужно используя оператор "->".
пример класса
Как я уже писал, классы, это для серьёзных проектов. На небольших задачках (примерах) они кажуться громоздкими и неудобными.
Трудно привести пример, где можно продемонстрировать только что-то одно. По этому, предлагаю вам код, который демонстрирует всё выше описанное.
Вот что вернула мне программка.
Как вы видете, здесь создаёться два объекта из одного класса.
Ему присваиваеться имя (это свойство).
А потом имя запрашиваеться (уже метод).
class и end class, я добавил, просто, чтобы было видно, где класс начинаеться, а где он заканчиваеться. Обратите внимание, что эти строки закоментированны.
заключение
freebasic поддерживает классы. И это очень хорошо.
см. также:
процедуры, функции и свойства
пользовательские типы данных
указатели (pointer).
введение
классы во FreeBasic есть!Тем, кому нужна теоретическая подготовка, то читать теорию ооп
Только выглядит это очень непривычно, по сравнению с некоторыми другими языками.
Дальше я буду рассказывать именно о реализации объектной модели в FreeBasic.
В принципе, бейсиковские типы данных, очень похожи на объекты, синтаксически.
Ну вот от сюда видимо исходили.
Класс объявляет конструкция type
- Код:
type class_name
...
end type
А внутри неё можно делать свойства. Это как по старому, с пользовательскими типами данных.
- Код:
' создаём класс
type mArray
' задаём свойства класса
dim key as string
dim value as string
end type
Но можно декларировать и методы, в качестве которых используются процедуры (sub) и функции (function). А вот здесь и начинаются необычности.
методы
Сама функция или процедура может находиться где угодно, но её имя должно начинаться с имени класса и точки.
- Код:
type mArray
' декларируем метод
declare function myfunc() as integer
end type
' тело метода
function mArray.myfunc() as integer
end function
Да, это весьма непривычно.
В C++ кажется что-то похожее, но там всё берётся в блок с ключевым словом class, а здесь такого нет. Возможно в будущих версиях ситуация измениться, но не будем загадывать.
активные свойства
Теперь об активных свойствах. Это вообще уникальное явление, которого я кроме бэйсика не где не встречал. Под свойствами я подразумеваю конструкцию property.
Это даже больше соответствует концепции ооп, чем в других языках. Там программисты использовали методы get и set.
Те кто знаком с visual basic знают property. Только они использовали ключевые слова get и let. А в FreeBasic они опущены. Это логично, поскольку по аргументам и так понятно, что к чему.
Для тех, кто не знает, рассказываю подробнее.
Конструкция property (свойство) - это функции которые принимают и возвращают свойства класса. Их должно быть две (обязательно иначе мой fb ругался). Причём
с одинаковыми именами.
- Код:
type mArray
declare property value() as string
declare property value( byVal nevVal as string)
end type
property mArray.value() as string
' это возвращатель, работает как функция
return "значение свойства"
end property
property mArray.value( byVal nevVal as string)
' это получатель, работает, как процедура
end property
Объекты
Объект это переменная, которая содержит экземпляр класса.
- Код:
dim a_object as mArray
Вот и всё. У нас уже есть объект a_object.
Ну а дальше поступаем с ним как хотим. Объект, являеться всего-лишь переменной.
Используя объект, мы можем обращаться к свойствам и методам экземпляра класса.
- Код:
' устанавливаем свойства
aObject.key = "freebasic"
aObject.value = "freebasic is programming language"
' читаем свойства
print "key = " & aObject.key
print "value = " & aObject.value
Как мы можем видеть, всё так, как было с пользовательским типом данных.
ключевое слово this
внутри класса, переодически приходится обращаться к текущему экземпляру. Ключевое слово this нужно писать вместо имени класса.
Это копия объекта внутри класса.
- Код:
type MyClass
declare sub PrnValue()
dim value as string
end type
sub MyClass.PrnValue()
' печатаем значение свойства
print "value = " & this.value
end sub
конструкторы и деструкторы
Помню, долго я искал их в vb6, запрятаны они были в странные слова, кои повторять нехочеться. А тут всё просто
constructor и destructor. Использовать нужно вместо sub.
- Код:
type mArray
' объявляем конструктор и деструктор
declare constructor()
declare destructor()
end type
' конструктор, запускаеться при создании экземпляра класса
constructor mArray()
print "объект инициирован"
end constructor
' деструктор, запускаеться при уничтожении экземпляра класса
destructor mArray()
print "объект завершен"
end destructor
Здорово? Вот бы везде так чётко.
Кажется конструкторов и деструкторов может быть несколько, но я ещё не проверял.
объекты по ссылке
Объекты по ссылке или указателю, мне показались более удобным решением, чем обычные. Чтобы понимать, о чём дальше пойдёт реч, ознакомьтесь с главой указатели (pointer).
Давайте познакомимся с двумя функциями.
new - создание объекта в памяти. Возвращает указатель, на объект.
- Код:
dim pObject as MyArray ptr
pObject = new MyArray
Такое объявление совершенно правильно и логично, хоть и выглядит громоздко. Возможно в будущих версиях всё измениться.
Функция new создаёт в памяти экземпляр указанного класса. Срабатывает конструктор, если таковой есть. А в указатель записываеться указатель на объект.
delete - удаляет объект из памяти. В качестве параметра передаёться указатель на объект.
- Код:
delete pObject
Память высвобождаеться, но перед этим запускаеться и отрабатывает деструктор.
Обращаться к методам и свойствам класса нужно используя оператор "->".
- Код:
pObject->value = "freebasic"
pObject->PrnValue()
пример класса
Как я уже писал, классы, это для серьёзных проектов. На небольших задачках (примерах) они кажуться громоздкими и неудобными.
Трудно привести пример, где можно продемонстрировать только что-то одно. По этому, предлагаю вам код, который демонстрирует всё выше описанное.
- Код:
' class Animals
' класс про зверушку
type Animals
declare constructor()
declare destructor()
declare function IsYourName() as integer
dim name as string ' свойство куда пишем имя зверушки
end type
' конструктор
constructor Animals()
' придумаем случайное имя
this.name = "Anonymous " & str(Int(Rnd(2) * 10) + 1)
' радуемся
print this.name & " is birth!"
end constructor
' деструктор
destructor Animals()
print this.name & " is did"
this.name = ""
end destructor
' метод который выводит имя
function Animals.IsYourName() as integer
print "mi name is '" & this.name & "'."
end function
' end class
randomize timer
' создаём переменные для указателя на объект
dim a as Animals pointer
dim b as Animals pointer
' создаём объект
print "create object"
a = new Animals
b = new Animals
' обзываем зверюшку
a->name = "Adolf"
b->name = "Bobik"
' как кого завут
a->IsYourName()
b->IsYourName()
' удаление объекта
print "kill object"
delete b
delete a
' конец программы
print "end"
sleep
Вот что вернула мне программка.
create object
Anonymous 4 is birth!
Anonymous 7 is birth!
mi name is 'Adolf'.
mi name is 'Bobik'.
kill object
Bobik is did
Adolf is did
end
Как вы видете, здесь создаёться два объекта из одного класса.
Ему присваиваеться имя (это свойство).
А потом имя запрашиваеться (уже метод).
class и end class, я добавил, просто, чтобы было видно, где класс начинаеться, а где он заканчиваеться. Обратите внимание, что эти строки закоментированны.
заключение
freebasic поддерживает классы. И это очень хорошо.
см. также:
процедуры, функции и свойства
пользовательские типы данных
указатели (pointer).
Последний раз редактировалось: Eric-S (Вс Авг 24, 2008 7:36 am), всего редактировалось 3 раз(а)
Re: классы, методы, свойства и объекты.
Сейчас перечитал эту главу и пришол в ужас. Почему же вы друзья не кричали и не возмущались, на такую лажу?
Дополнил её, но это не всё.
Жду конструктивной критики и хороших предложений.
Дополнил её, но это не всё.
Жду конструктивной критики и хороших предложений.
Re: классы, методы, свойства и объекты.
Я нелюбитель ооп-а, да и мало в нем понимаю, моетому и молчу))
Re: классы, методы, свойства и объекты.
У меня возникли вот такие вопросы:
1)"создаём класс
type mArray
dim key as string"
Нужен ли DIM или можно обойтись без него?
2)"type mArray
' декларируем метод
declare function myfunc() as integer
end type
"
Метод, как я понимаю, описывается потом в Function, но что его связывает с объектом? Как они взаимосвязаны
3) блин, честно признаться я почти ничего не понимаю =(
я хотел бы знать для чего это можно применять на практике. С бобиком и Адольфом не в ладах я
4) (офтопик) просто спрашиваю: byVal - для чего это? и как называется обозначение для переменной (типа string) которое допускает значение от 0 до 255, если конечно есть
6) получатель чем отличается от процедуры?
7) как в деструкторе освобождать память (допустим есть объект - массив, как в деструкторе его удалить, или же он сам удаляется после вызова деструктора (имею ввиду: delete нужен?))
9)возможно ли нарушение работы программ, если неправильно указан адрес на переменную? или бейсик не даёт этого сделать?
P.S. извините, что я такой надоедливый, но мне это позарез нужно, особенно всё связанное с длл-ками и ооп
1)"создаём класс
type mArray
dim key as string"
Нужен ли DIM или можно обойтись без него?
2)"type mArray
' декларируем метод
declare function myfunc() as integer
end type
"
Метод, как я понимаю, описывается потом в Function, но что его связывает с объектом? Как они взаимосвязаны
3) блин, честно признаться я почти ничего не понимаю =(
я хотел бы знать для чего это можно применять на практике. С бобиком и Адольфом не в ладах я
4) (офтопик) просто спрашиваю: byVal - для чего это? и как называется обозначение для переменной (типа string) которое допускает значение от 0 до 255, если конечно есть
6) получатель чем отличается от процедуры?
7) как в деструкторе освобождать память (допустим есть объект - массив, как в деструкторе его удалить, или же он сам удаляется после вызова деструктора (имею ввиду: delete нужен?))
9)возможно ли нарушение работы программ, если неправильно указан адрес на переменную? или бейсик не даёт этого сделать?
P.S. извините, что я такой надоедливый, но мне это позарез нужно, особенно всё связанное с длл-ками и ооп
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
Нет, dim не обязателен, но я бы рекомендовал его писать. Всего 4 символа, а код будет чуть понятнее.Gena пишет:1)"создаём класс
type mArray
dim key as string"
Нужен ли DIM или можно обойтись без него?
Перед именем метода, мы указываем имя соответствующего класса.Gena пишет:
2)"type mArray
' декларируем метод
declare function myfunc() as integer
end type
"
Метод, как я понимаю, описывается потом в Function, но что его связывает с объектом? Как они взаимосвязаны
function myarray.myfunc() as integer
Ндя... Собственно ради ответа на этот вопрос и писалась "теория ооп". Короче, классы нужны, чтобы более легко писать сложные программы. Но часто трудно понять, когда стоит пользовать классы. Это уже приходит с опытом.Gena пишет:
3) блин, честно признаться я почти ничего не понимаю =(
я хотел бы знать для чего это можно применять на практике. С бобиком и Адольфом не в ладах я
Стучите мне в аську и расскажите, над чем вы работаете.
byVal или byRef это ключевые слова, которые говорят как нужно поступать с переменной, передавать копию её значения, или передавать ссылку на значение, соответственно. Смотрите https://freebasic.forum2x2.ru/forum-f10/tema-t49.htmGena пишет:
4) (офтопик) просто спрашиваю: byVal - для чего это? и как называется обозначение для переменной (типа string) которое допускает значение от 0 до 255, если конечно есть
Про string не понял вопроса.
Gena пишет:
6) получатель чем отличается от процедуры?
Это уже зависит от тех данных, которые у вас есть.Gena пишет:
7) как в деструкторе освобождать память (допустим есть объект - массив, как в деструкторе его удалить, или же он сам удаляется после вызова деструктора (имею ввиду: delete нужен?))
Если вы начали извращаться с захватом памяти, то конечно вам нужно высвобождать её.
А обычно можно просто обнулить переменные.
i = 0 ' integer
s = "" ' string
Или не делать этого. Опять же что целесообразнее. Стандартные переменные, у вас однозначно очистяться. А что будет с памятью, которую вы захватывали, мне лично непонятно. По сему я освобождаю, во избежании проблем.
Если вы включите расширенную обработку ошибок. (при компиляции ключик -exx), то ваша прога будет ругаться на непонятное. Иначе будет считать, что так и надо. Ну и соответственно результат непредсказуем.Gena пишет:
9)возможно ли нарушение работы программ, если неправильно указан адрес на переменную? или бейсик не даёт этого сделать?
[/quote]Gena пишет:P.S. извините, что я такой надоедливый, но мне это позарез нужно, особенно всё связанное с длл-ками и ооп
Ничо. Переживём. Сами были такими. Да впрочем и есть.
freebasic к моему сожалению ооп поддерживает только частично. Вот и приходиться извращаться. А также надеяться на новые версии.
А вот dll гораздо лучше многих других. Про activeX и com я молчу, поскольку это и не совсем даже dll.
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
new/delete можно не использовать, а заключить переменную типа нашего типа-класса в блок Scope-End Scope. И тогда деструктор тоже вызывается.
vbman- Сообщения : 52
Дата регистрации : 2008-11-19
Возраст : 42
Откуда : Украина, Кировоград
Re: классы, методы, свойства и объекты.
Прошол уже год.
Я сейчас знаю много больше и наверное следует главу переработать.
Постараюсь сделать это в ближайшее время.
Ведь, гэ-ха-эм. Я сию главу писал, когда ещё сам пытался подружиться с ооп во freebasic'е.
Надо бы наверное какой-нибудь жизненный и полезный примерчик сделать. И у меня даже есть один на примете, правда там конкретный изврат с указателями на функции. Так что он не очень подойдёт в качестве простого.
Чего бы такого замутить интересного?
Может быть классику с домашними любимцами, студентами или работниками фирмы?
Я сейчас знаю много больше и наверное следует главу переработать.
Постараюсь сделать это в ближайшее время.
Ведь, гэ-ха-эм. Я сию главу писал, когда ещё сам пытался подружиться с ооп во freebasic'е.
Надо бы наверное какой-нибудь жизненный и полезный примерчик сделать. И у меня даже есть один на примете, правда там конкретный изврат с указателями на функции. Так что он не очень подойдёт в качестве простого.
Чего бы такого замутить интересного?
Может быть классику с домашними любимцами, студентами или работниками фирмы?
Re: классы, методы, свойства и объекты.
Я никогда раньше не пользовался лично new/delete, но у меня в этом возникла необходимость:
Я не могу создавать доступный для всей программы массив в подпрограмме, но зато можно как-то выкрутиться с помощью New/Delete, поскажите как.
План таков:
вызывается подпрограмма LoadText(nmoft as string)
условно говоря считается количество строчек, создаётся массив в памяти
массив заполняется текстом
и указатель на массив (и его длина) являются результатом функции.
Помогите написать программу, плиз! (Как бэ отправную точку, пример)
Я не могу создавать доступный для всей программы массив в подпрограмме, но зато можно как-то выкрутиться с помощью New/Delete, поскажите как.
План таков:
вызывается подпрограмма LoadText(nmoft as string)
условно говоря считается количество строчек, создаётся массив в памяти
массив заполняется текстом
и указатель на массив (и его длина) являются результатом функции.
Помогите написать программу, плиз! (Как бэ отправную точку, пример)
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
С одной стороны задачка выглядит простой. Но тут уже надо посмотреть на конкретную ситуацию.
Давайте будем рассуждать по шагам.
1.
функция должна возвращать указатель на объект. Иначе вернуть указатель на массив и его размер нельзя.
Значит нам нужен класс, нечто вроде такого:
2.
Дальше надо управлять этим буфером. Заполнить его, а потом освободить.
Соответственно нужен конструктор и деструктор.
Вот, примерно так. Не забываем, что конструктор и деструктор нужно объявить в классе.
3.
Теперь нам надо работать с этим объектом.
Вот так вот. Всё довольно просто.
Главное не забывать разрушать объекты иначе будет утечка памяти.
И ещё не путать операторы new[] и delete[]
с операторами new и delete.
В данном примере я показал и те и другие в действии.
new[] резервирует память для буфера, а delete[] её соответственно освобождает.
Операторы же new создают объект и вызывают его конструкторы, а delete разрушают обект вызывая его деструктор и освобождая память занимаемую объектом.
4.
Кстати статическое свойство класса, превосходно заменяет глобальную переменную.
Вот другое решение. Оно может показаться более простым, но имхо, мороки больше.
Возможно этот пример выглядит проще. Но придётся уже самостоятельно следить за каждым буфером value. И самое запарное - передавать в функции не один указатель на объект, а два параметра: указатель на буфер и его длину.
В принципе, как я только что сказал Электрику, вместо new[] можно использовать allocate() или callocate(), которые по сути являются функциями malloc() и calloc() языка C. Но их использовать не рекомендуется.
Отличия в том, что new[] возвращает уже указатель приведённый к нужному типу.
Кроме того функция malloc() требует указания размера в байтах, а new[] число элементов, размер она вычисляет уже сама.
Если произошла ошибка то new[] и new, так же как и allocate() с callocate() возвращают 0.
С оператором delete[] история похожа. Можно освобождать память функцией deallocate(), но ей нужно передавать именно указатель.
На 0 она может ругнуться.
А delete[] промолчит.
Аналогом deallocate() является функция free() из языка C.
Не освобождайте уже освобождённую память.
Может случиться чего-нибудь страшное, например освободиться уже освобождённая память и занятая потом чем-нибудь другим нужным.
Кстати именно по этому я обнуляю указатели сразу после освобождения памяти.
Вот Электрик жалуется, что когда используешь new и delete вместо callocate() и deallocate() размер програмы увеличивается на пару килобайт.
На этот счёт ничего не могу сказать.
Возможно что-то подключается виндовое или позаимстванное из библиотек C++.
Давайте будем рассуждать по шагам.
1.
функция должна возвращать указатель на объект. Иначе вернуть указатель на массив и его размер нельзя.
Значит нам нужен класс, нечто вроде такого:
- Код:
type SString
' указатель на строковый буфер
dim value as zstring ptr
' длина буфера
dim length as integer
end type
2.
Дальше надо управлять этим буфером. Заполнить его, а потом освободить.
Соответственно нужен конструктор и деструктор.
- Код:
' конструктор
constructor SString( byRef as string )
' берём длину строки
length = len(s)
' резервируем память для буфера
value = new zstring[ length + 1 ]
' скопируем строчку в буфер
dim i as integer
for i = 0 to length
value[i] = s[i]
next
' поставим терминальный ноль
value[length] = chr(0)
' хотя в принципе он должен был быть уже скопирован, так что это формальность
end constructor
' деструктор
destructor SString()
' обязательно нужно освободить память занятую буфером
delete[] value
' и для формальности обнуляем свойства
value = 0
length = 0
end destructor
Вот, примерно так. Не забываем, что конструктор и деструктор нужно объявить в классе.
3.
Теперь нам надо работать с этим объектом.
- Код:
function Foot( byRef s as string ) as SString ptr
' создаём указатель для обекта
dim o as SString ptr
' создаём объект, проинициализировав его полученной строкой
o = new SString( s )
' возвращаем из функции указатель на объект
return 0
end function
' главная процедура
sub main()
' создаём строчку
dim str1 as string
str1 = "Hello, world!"
' создаём указатель на объект
dim o as SString ptr
' передаём строку в функцию и получаем указатель на объект
o = Foot( str1 )
' ну тут мы чего-нибудь делаем.
print "длина строки: "; o->length
' покажем строку
print "строка:"
print mid( *o->value, 1, o->length )
' после того как объект нам уже не нужен, его нужно обязательно разрушить
delete o
' обнулим указатель
o = 0
end sub
Вот так вот. Всё довольно просто.
Главное не забывать разрушать объекты иначе будет утечка памяти.
И ещё не путать операторы new[] и delete[]
с операторами new и delete.
В данном примере я показал и те и другие в действии.
new[] резервирует память для буфера, а delete[] её соответственно освобождает.
Операторы же new создают объект и вызывают его конструкторы, а delete разрушают обект вызывая его деструктор и освобождая память занимаемую объектом.
4.
Кстати статическое свойство класса, превосходно заменяет глобальную переменную.
Вот другое решение. Оно может показаться более простым, но имхо, мороки больше.
- Код:
' процедура, которая создаёт буфер
sub Foot( byVal s as string, byRef value as zstring ptr, byRef length as integer )
' берём длину строки
length = len(s)
' резервируем память для буфера
value = new zstring[ length + 1 ]
' скопируем строчку в буфер
dim i as integer
for i = 0 to length
value[i] = s[i]
next
' поставим терминальный ноль
value[length] = chr(0)
end sub
' главная процедура
sub main()
' создаём строчку
dim str1 as string
str1 = "Hello, world!"
' создаём указатель на буфер
dim value as zstring ptr
' размер буфера
dim length as integer
' передаём строку в процедуру
Foot( s, value, length )
' ну тут мы чего-нибудь делаем.
print "длина строки: "; length
' покажем строку
print "строка:"
print mid( *value, 1, length )
' а тут мы очищаем буфер
delete[] value
' обнулим указатель
value = 0
end sub
Возможно этот пример выглядит проще. Но придётся уже самостоятельно следить за каждым буфером value. И самое запарное - передавать в функции не один указатель на объект, а два параметра: указатель на буфер и его длину.
В принципе, как я только что сказал Электрику, вместо new[] можно использовать allocate() или callocate(), которые по сути являются функциями malloc() и calloc() языка C. Но их использовать не рекомендуется.
Отличия в том, что new[] возвращает уже указатель приведённый к нужному типу.
Кроме того функция malloc() требует указания размера в байтах, а new[] число элементов, размер она вычисляет уже сама.
Если произошла ошибка то new[] и new, так же как и allocate() с callocate() возвращают 0.
С оператором delete[] история похожа. Можно освобождать память функцией deallocate(), но ей нужно передавать именно указатель.
На 0 она может ругнуться.
А delete[] промолчит.
Аналогом deallocate() является функция free() из языка C.
Не освобождайте уже освобождённую память.
Может случиться чего-нибудь страшное, например освободиться уже освобождённая память и занятая потом чем-нибудь другим нужным.
Кстати именно по этому я обнуляю указатели сразу после освобождения памяти.
Вот Электрик жалуется, что когда используешь new и delete вместо callocate() и deallocate() размер програмы увеличивается на пару килобайт.
На этот счёт ничего не могу сказать.
Возможно что-то подключается виндовое или позаимстванное из библиотек C++.
Re: классы, методы, свойства и объекты.
Вот что я наделал ). По идее всё правильно. Происходит плохая вещь - ошибка! И в диспечере задач остаётся процесс и его завершить нельзя. =( Что неправильно?
- Код:
#Include "fbgfx.bi"
Type myglVertOnTriangleT
x As Double
y As Double
z As Double
U As Double
V As Double
End Type
Type myglTriangleT
T(1 To 3) As myglVertOnTriangleT
NomTex As Integer
End Type
Type Result
ukaz As myglTriangleT Ptr
kolvo As Integer
End Type
Declare Function LoadLevel(nmoft As string) As Result
Dim Level As Result
Dim Shared As String s0
Dim Shared As Integer i0
Level=LoadLevel("map01")
ScreenRes 640,480,32
trg=*Level.ukaz
Print trg.NomTex
Do
Sleep 10
Loop Until MultiKey(fb.SC_ESCAPE)
Delete[] Level.ukaz
Function LoadLevel(nmoft As string) As Result
Dim res As Result
Dim trg As myglTriangleT
Dim mesto As Integer
Open ExePath+"\maps\"+nmoft+"\treugs.txt" For Input As #2
Do
Input #2,trg.NomTex
Input #2,trg.T(1).x,trg.T(1).y,trg.T(1).z,trg.T(1).U,trg.T(1).V
Input #2,trg.T(2).x,trg.T(2).y,trg.T(2).z,trg.T(2).U,trg.T(2).V
Input #2,trg.T(3).x,trg.T(3).y,trg.T(3).z,trg.T(3).U,trg.T(3).V
Input #2,s0
Res.kolvo+=1
Loop Until Eof(2)
Res.ukaz= New myglTriangleT[Res.kolvo]
Seek 2,1
For i0=1 To Res.kolvo
Input #2,trg.NomTex
Input #2,trg.T(1).x,trg.T(1).y,trg.T(1).z,trg.T(1).U,trg.T(1).V
Input #2,trg.T(2).x,trg.T(2).y,trg.T(2).z,trg.T(2).U,trg.T(2).V
Input #2,trg.T(3).x,trg.T(3).y,trg.T(3).z,trg.T(3).U,trg.T(3).V
Input #2,s0
*Res.ukaz=trg
Res.ukaz=Res.ukaz+SizeOf(Result)
Next
Close #2
Return res
End Function
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
Уф! Меня от сплошного кода, без единого комента просто приплющило.
Я в этой каше буду разбираться только под очень особое настроение.
Попробуй тестить по кускам.
Я в этой каше буду разбираться только под очень особое настроение.
Попробуй тестить по кускам.
Re: классы, методы, свойства и объекты.
Извиняюсь! Я только недавно понял, что поставил планку слишком высоко - я никак с одной простейшей проблемой не могу разобраться - она в разделе для начинающих.
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
Я разобрался и понял, что new[] и delete[] - очень полезные функции - они с учпехом заменяют оператор DIM в функциях, и я думаю, что в будущем сделают нормальный оператор, который можно будет использовать и в основной программе и в функциях(то есть оператор Dim Shared в функции)
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
Операторы new[] и delete[] к dim shared отношения не имеют.
Это разные вещи. Кстати причём здесь функции?
Вообще
dim shared ... это по определению не может быть внутри функций.
Внутри функций используй простой dim.
Это так называемый статический массив.
Он создаётся в нутри области видимости, а потом автоматически разрушаеться, когда область закрываеться.
Оператор new[] создаёт уже динамический массив, который от области видимости не зависит.
Но его нужно разрушать в ручную, оператором delete[].
Врят ли в этом направлении будет что-то меняться.
Но никто не запрещает сделать класс обёртку для массива.
И его можно будет уже использовать почти как привычный массив.
Не знаю, не тестил. Но вроде бы всё правильно.
Причём указатель на этот объект можно сделать глобальным или кидать его из одной функции в другую.
Это разные вещи. Кстати причём здесь функции?
Вообще
dim shared ... это по определению не может быть внутри функций.
Внутри функций используй простой dim.
Это так называемый статический массив.
Он создаётся в нутри области видимости, а потом автоматически разрушаеться, когда область закрываеться.
Оператор new[] создаёт уже динамический массив, который от области видимости не зависит.
Но его нужно разрушать в ручную, оператором delete[].
Врят ли в этом направлении будет что-то меняться.
Но никто не запрещает сделать класс обёртку для массива.
- Код:
type Array
declare constructor( byVal r as integer )
declare destructor()
private:
' указатель на буфер
buf as integer ptr
' размер буфера
length as integer
end type
' конструктор
constructor Array( byVal r as integer )
' резервируем память
buf = new integer[r]
length = r
end constructor
' деструктор
destructor Array()
' освобождаем память
delete[] buf
buf = 0
length = 0
end destructor
' устанавливает значение
property Array.item( byVal n as integer, byVal v as integer )
if n > 0 and n <= length then
buf[n-1] = v
end if
end property
' возвращает значение
property Array.item( byVal n as integer ) as integer
if n > 0 and n <= length then
return buf[n-1]
else
' указан неверный индекс
return 0
end if
end property
И его можно будет уже использовать почти как привычный массив.
- Код:
' создаём указатель
dim d as Array ptr
' создаём массив на 10 'элементов
d = new Array( 10 )
' помещаем значения
for i = 1 to 10
d->item(i) = i * i
next
' выводим значения
for i = 1 to 10
print d->item(i)
next
' разрушаем массив
delete d
Не знаю, не тестил. Но вроде бы всё правильно.
Причём указатель на этот объект можно сделать глобальным или кидать его из одной функции в другую.
Re: классы, методы, свойства и объекты.
А вот я, ели чесно, считаю что использовать type для классов неправильно. Всетаки он использовался как некая фиксированная структура данных, да и к тому же недавно в мане наткнулся на такую весч как class, хоть там пока ниче и нету, но следует ожидать что скоро появится, и я непредставляю как они будут вместе сожительствовать, имхо для классов надо было бы сразу делать отдельную конструкцию, а тк они просто обязаны сохранить совместимость (я надеюсь на это), то получится жуткая каша
Re: классы, методы, свойства и объекты.
Я это зарезервированное слово видел уже давно в мануале.
И тут всё действительно очень странно.
Начиналось ведь с простого описания типа type .. end type.
Ни о каких конструкторах деструкторах и методах речи не было.
Но после конструкция type стала всё больше напоминать структуру из языка C++.
Я если честно надеюсь, что class исправит ситуацию.
И если грамотно подойти, не передирая напрямую из C++ то может получиться очень даже удобно.
Вот например так
Ну и добавить сюда ещё ключевых слов.
static - статический метод / свойство
virtual - виртуальный метод
final - неперегружаемый метод
inline - раскрывающийся метод / конструктор / деструктор
Очень даже мило выйдет. Причём без всяких конфликтов с type.
А вот над наследованием нужно подумать.
{abstract|interface|} class [class_name] { extends base_class }
Но это место весьма спорно.
А делать class синонимом type действительно не стоит.
Хотя есть во всём этом ещё одна проблема.
Если конструкция type .. end type мне позволяет описать класс в начале программы, а в конце программы уже оформить его методы.
То с class такого не получиться, нужно будет описывать всё сразу.
Но если в методе нужны другие классы или структуры ещё не описанные
то счастье накрываеться.
Я вижу здесь одно решение, которое в корни расходиться с языком C++. И может быть сложнореализуемо.
Компилятор должен за первый проход выбрать классы и постараться их связно оформить.
Таким образом чтобы объявление класса было действительным до и после его описания.
И только после всего этого компилировать программу.
Но тут если пойти по более простому пути, можно нарваться на одну бяку. В таких классах, нельзя будет создать в качестве свойства объект другого класса.
А более сложный путь со сравнениями и переборами, может оказаться накладным.
И тут всё действительно очень странно.
Начиналось ведь с простого описания типа type .. end type.
Ни о каких конструкторах деструкторах и методах речи не было.
Но после конструкция type стала всё больше напоминать структуру из языка C++.
Я если честно надеюсь, что class исправит ситуацию.
И если грамотно подойти, не передирая напрямую из C++ то может получиться очень даже удобно.
Вот например так
- Код:
class SomeClass
declare function method1() as integer
private:
dim value as integer
public:
constructor()
print "объект создан"
end constructor
destructor()
print "объект разрушен"
end type
function method1() as integer
return value
end function
end class
Ну и добавить сюда ещё ключевых слов.
static - статический метод / свойство
virtual - виртуальный метод
final - неперегружаемый метод
inline - раскрывающийся метод / конструктор / деструктор
Очень даже мило выйдет. Причём без всяких конфликтов с type.
А вот над наследованием нужно подумать.
{abstract|interface|} class [class_name] { extends base_class }
Но это место весьма спорно.
А делать class синонимом type действительно не стоит.
Хотя есть во всём этом ещё одна проблема.
Если конструкция type .. end type мне позволяет описать класс в начале программы, а в конце программы уже оформить его методы.
То с class такого не получиться, нужно будет описывать всё сразу.
Но если в методе нужны другие классы или структуры ещё не описанные
то счастье накрываеться.
Я вижу здесь одно решение, которое в корни расходиться с языком C++. И может быть сложнореализуемо.
Компилятор должен за первый проход выбрать классы и постараться их связно оформить.
Таким образом чтобы объявление класса было действительным до и после его описания.
И только после всего этого компилировать программу.
Но тут если пойти по более простому пути, можно нарваться на одну бяку. В таких классах, нельзя будет создать в качестве свойства объект другого класса.
А более сложный путь со сравнениями и переборами, может оказаться накладным.
Re: классы, методы, свойства и объекты.
Спасибо, Eric-S, я это понимаю, наверно я просто не так выразился )
Кстати, недавно наткнулся на такую конструкцию - экономит место.
Я не понимаю, зачем нужно в классе создавать метод? Как это применить? Ведь можно использовать обычные функции. Приведите пример, пожалуйста(Меня интересует именно смысл).
Также я не понимаю активных свойств - в чём смысл их существования?
Кстати, недавно наткнулся на такую конструкцию - экономит место.
- Код:
Type v3
As Double x,y,z
End Type
Я не понимаю, зачем нужно в классе создавать метод? Как это применить? Ведь можно использовать обычные функции. Приведите пример, пожалуйста(Меня интересует именно смысл).
Также я не понимаю активных свойств - в чём смысл их существования?
Gena- Сообщения : 182
Дата регистрации : 2008-11-05
Возраст : 31
Откуда : Москва
Re: классы, методы, свойства и объекты.
Ща немного трепотни, но будет и поделу. Советую прочитать всё.
Во первых класс, это своего рода пространство имён. О которых я уже писал на форуме, и скоро (надеюсь) переработаю в отдельную главу.
Говоря простым языком делая метод, а не функцию ты просто связываешь её с этим классом.
Во-вторых класс это закрытая конструкция.
К сожалению я просто о принципах инкапсуляции очень мало писал.
Постараюсь исправиться.
Метод он работает со свойствами объекта напрямую.
А функцию, вам бы пришлось передавать в неё множество параметров.
Ну вот например создадим класс, который будет рисовать муху и перемещать её по экрану.
(Сразу скажу, что я не собираюсь тут рисовать, а даю всё схематично!
Я со школы не использовал эти функции get() и put() и уже забыл, если кто напомнит, то будет не плохо!)
Вот так вот упращаеться управление нашей мухой.
И таким образом мы можем создать не одну а несколько мух, причём с разными картинками.
Причём не будем путаться с лишними переменными.
Да и с лишними параметрами функций.
Кстати, поскольку два метода и все свойства у нас приватные, мы не сможем их изменить.
Точнее кто-то чужой, кто захочет поиграться с нашей мухой.
А теперь представьте в какое мясо превратиться программа, если в ней использовать десяток мух?
На каждую муху надо будет создавать в ручную два буфера памяти плюс координаты.
Конечно это можно будет засунуть в структуру очень похожую, но функции из красивых, превратяться в уродливые конструкции.
Надеюсь разница между методом и функцией заметна?
Кстати, хочу обрадовать, что в первый раз муху придёться прорисовывать вручную, вызывая функцию Muha_paint()
А потом стирать её вызывая функцию Muha_hidden()
Ох! И не забыв передать в неё указатель на описание самой мухи!
В прочем это не так страшно, не всё ли равно писать
или же
Кому как, но мне лень!
Я даже набивая этот пример ругался сквозь зубы.
Во первых класс, это своего рода пространство имён. О которых я уже писал на форуме, и скоро (надеюсь) переработаю в отдельную главу.
Говоря простым языком делая метод, а не функцию ты просто связываешь её с этим классом.
Во-вторых класс это закрытая конструкция.
К сожалению я просто о принципах инкапсуляции очень мало писал.
Постараюсь исправиться.
Метод он работает со свойствами объекта напрямую.
А функцию, вам бы пришлось передавать в неё множество параметров.
Ну вот например создадим класс, который будет рисовать муху и перемещать её по экрану.
(Сразу скажу, что я не собираюсь тут рисовать, а даю всё схематично!
Я со школы не использовал эти функции get() и put() и уже забыл, если кто напомнит, то будет не плохо!)
- Код:
' class муха
type Muha
declare constructor( x as integer, y as integer, obraz() as integer )
declare destructor()
declare sub move( xv as integer, yv as integer )
private:
' а это будет доступно только ввнутри класса
declare sub hidden()
declare sub paint()
' массив для нашего рисунка
dim obraz(1 to 9, 1 to 9 ) as integer
' то что было нарисовано раньше
dim old(1 to 9, 1 to 9 ) as integer
' текущие координаты
dim as integer x, y
end type
' метод рисующий муху в текущем положении
sub Muha.paint()
' сначало сохраним то что унас в этой области экрана
get old, x - 4, y - 4, x + 4, y + 4
' а теперь нарисуем саму муху
put obraz, x - 4, y - 4, x + 4, y + 4
end sub
' метод скрывающий муху из текущего положения
sub Muha.hidden()
' суть операции заключаеться в том, чтобы на этом месте нарисовать старую картинку
put old, x - 4, y - 4, x + 4, y + 4
end sub
' конструктор
constructor Muha( x as integer, y as integer, obraz() as integer )
' копируем переданные значения
this->x = x
this->y = y
this->obraz = obraz
paint()
end constructor
' деструктор
destructor Muha()
' стираем муху
hidden()
end destructor
' метод для перемещение мухи
sub Muha.move( xv as integer, yv as integer )
' сначала нужно стереть муху из текущего положения
hidden()
' изменим координаты
x += vx
y += vy
' нарисовать муху в новом месте
paint()
end sub
' end class
Вот так вот упращаеться управление нашей мухой.
- Код:
' сделаем картинку мухи
dim obraz_muhi(1 to 9, 1 to 9) as integer
' понятия не имею что туда фигачить, можете даже не муху а что угодно
' поточечно рисуем
obraz_muhi(4,4) = 128
' а теперь создадим объект мухи
dim m1 as Muha ptr
m1 = new Muha( 40, 40, obraz_muhi )
' переместим её куда-нибудь, задав только вектор движения
m1->move( 2, -1 )
' удаляем муху
delete m1
И таким образом мы можем создать не одну а несколько мух, причём с разными картинками.
Причём не будем путаться с лишними переменными.
Да и с лишними параметрами функций.
Кстати, поскольку два метода и все свойства у нас приватные, мы не сможем их изменить.
Точнее кто-то чужой, кто захочет поиграться с нашей мухой.
А теперь представьте в какое мясо превратиться программа, если в ней использовать десяток мух?
На каждую муху надо будет создавать в ручную два буфера памяти плюс координаты.
Конечно это можно будет засунуть в структуру очень похожую, но функции из красивых, превратяться в уродливые конструкции.
- Код:
' функция рисующая муху в текущем положении
sub Muha_paint( m as Muha ptr )
' сначало сохраним то что унас в этой области экрана
get m->old, m->x - 4, m->y - 4, m->x + 4, m->y + 4
' а теперь нарисуем саму муху
put m->obraz, m->x - 4, m->y - 4, m->x + 4, m->y + 4
end sub
' функция скрывающая муху из текущего положения
sub Muha.hidden( m as Muha ptr )
' суть операции заключаеться в том, чтобы на этом месте нарисовать старую картинку
put m->old, m->x - 4, m->y - 4, m->x + 4, m->y + 4
end sub
' конструктор
' функция для перемещение мухи
sub Muha_move( m as Muha ptr, xv as integer, yv as integer )
' сначала нужно стереть муху из текущего положения
hidden( m )
' изменим координаты
m->x += vx
m->y += vy
' нарисовать муху в новом месте
paint( m )
end sub
' end class
Надеюсь разница между методом и функцией заметна?
Кстати, хочу обрадовать, что в первый раз муху придёться прорисовывать вручную, вызывая функцию Muha_paint()
А потом стирать её вызывая функцию Muha_hidden()
Ох! И не забыв передать в неё указатель на описание самой мухи!
В прочем это не так страшно, не всё ли равно писать
- Код:
muha_1->move( 13, 3 )
или же
- Код:
muha_move( muha_1, 3, 3 )
Кому как, но мне лень!
Я даже набивая этот пример ругался сквозь зубы.
Re: классы, методы, свойства и объекты.
Что же касаеться активных свойств.
Ну вот, опять наша муха.
Как вы думаете, где она может находиться? Какие у неё могут быть координаты?
Насколько я помню это очень относительно, ведь экранчики бывают разные. Но ладно, допустим что только 640 x 480.
А что будет если бы мы сделали свойства не приватными? А потом попытались бы их изменить?
Ведь это неверные значения! Значения должны быть
x = 1 to 640
y = 1 to 480
Кстати, разве с такими значениями удобно работать? Ведь если бы они были к примеру
x = 1 to 1000
y = 1 to 1000
То было бы более удобно. Не правда ли?
Ну вот, а пересчитывать это всё по сто раз в методах, тоже не удобно. Это будет кушать лишние ресурсы. По этому мы можем сделать спецальную функцию. Но синтаксис функций, не всегда удобен. Зато активные свойства очень даже в тему.
Давайте сделаем свойство для x. для y вы и сами сможете.
Кстати, наверное внутри, класса x и y нужно переименовать,выполнив поиск и замену слова.
Теперь у нас будет класс
Ну и добавляем активные свойство
И теперь для мухи наш код будет верен
Муха сразу же будет перерисована в новом месте! Не нужно даже ничего вызывать!
А координаты центра экрана понятны интуитивно, не нужно брать калькулятор.
Короче активное свойство это своеобразный фильтр и преобразователь для значений передаваемых в простые свойства.
Но поскольку активное свойство по своей сути являеться функцией, то вы можете пихать туда что угодно.
Ну вот, опять наша муха.
Как вы думаете, где она может находиться? Какие у неё могут быть координаты?
Насколько я помню это очень относительно, ведь экранчики бывают разные. Но ладно, допустим что только 640 x 480.
А что будет если бы мы сделали свойства не приватными? А потом попытались бы их изменить?
- Код:
m1->x = 500
m1->y = 500
m1->move(1,1)
Ведь это неверные значения! Значения должны быть
x = 1 to 640
y = 1 to 480
Кстати, разве с такими значениями удобно работать? Ведь если бы они были к примеру
x = 1 to 1000
y = 1 to 1000
То было бы более удобно. Не правда ли?
Ну вот, а пересчитывать это всё по сто раз в методах, тоже не удобно. Это будет кушать лишние ресурсы. По этому мы можем сделать спецальную функцию. Но синтаксис функций, не всегда удобен. Зато активные свойства очень даже в тему.
Давайте сделаем свойство для x. для y вы и сами сможете.
Кстати, наверное внутри, класса x и y нужно переименовать,выполнив поиск и замену слова.
Теперь у нас будет класс
- Код:
type Muha
declare constructor( x as integer, y as integer, obraz() as integer )
declare destructor()
declare sub move( xv as integer, yv as integer )
property x() as integer
property x( as integer )
private:
' а это будет доступно только ввнутри класса
declare sub hidden()
declare sub paint()
' массив для нашего рисунка
dim obraz(1 to 9, 1 to 9 ) as integer
' то что было нарисовано раньше
dim old(1 to 9, 1 to 9 ) as integer
' текущие координаты
dim as integer coord_x, coord_y
end type
Ну и добавляем активные свойство
- Код:
' возвращает пересчитанное значение координаты по оси x
property Muha.x() as integer
return coord_x * (1000 / 640)
end property
' устанавливает новое значение координаты по оси x
property Muha.x( v as integer )
if (v > 10) and (v < 990( then
' если координата задана в допустимом диапазоне, то сохраняем свойство
coord_x = v / (100 / 640)
' удалим муху со старого места
hidden()
' и нарисуем в новом
paint()
end if
end property
И теперь для мухи наш код будет верен
- Код:
m1->x = 500
m1->y = 500
Муха сразу же будет перерисована в новом месте! Не нужно даже ничего вызывать!
А координаты центра экрана понятны интуитивно, не нужно брать калькулятор.
Короче активное свойство это своеобразный фильтр и преобразователь для значений передаваемых в простые свойства.
Но поскольку активное свойство по своей сути являеться функцией, то вы можете пихать туда что угодно.
Страница 1 из 1
Права доступа к этому форуму:
Вы не можете отвечать на сообщения