С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397

Доступ к полям класса пользовательских типов

09.08.2024, 13:36. Показов 1125. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Предыстория.
Есть у меня игровой проект, шутер FPS, в нём изначально был один персонаж. Все его параметры и физика собраны в отдельном модуле (не классе). Решил переделать на мультиплеер (пока с ботами), соответственно модуль переделал на класс. И вот тут начинаются проблемы.
Некоторые Public поля пользовательских типов (структуры), класс такое не позволяет. Вроде бы, решение простое - делаем поля Private и оборачиваем его в Property. Public Property таких типов тоже недопустимы, но тут спасает ключевое слово Friend.
Но! Многие функции и процедуры математики реализованы так, что возвращают значение через ByRef параметр, а не как возврат в функции, но такой возврат перестаёт работать, когда к структуре мы получаем доступ через Property.
Пример. Процедура vAdd суммирует вектора vIn1 и vIn2 и возвращает значение в vOut:

Visual Basic
1
2
3
4
Private Sub vAdd(vOut As Vector, vIn1 As Vector, vIn2 As Vector)
  vOut.x = vIn1.x + vIn2.x
  vOut.y = vIn1.y + vIn2.y
End Sub
Так работает (V0, V1, V2 - вектора):
Visual Basic
1
vAdd V0, V1, V2
А так не работает (T.V - вектор, находящийся в экземпляре класса):
Visual Basic
1
vAdd T.V, V1, V2
Я понимаю, что можно решить так:
Visual Basic
1
2
vAdd V0, V1, V2
T.V = V0
Но хочется красивого решения. Мысли будут?

Прилагаю минимальный тестовый проект.
Вложения
Тип файла: zip ClassStruct.zip (1.6 Кб, 4 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.08.2024, 13:36
Ответы с готовыми решениями:

Доступ к полям класса через переменные другого класса
Уважаемые коллеги! Почему в моделях Аnylogic для упрощения доступа к полям одного класса (класс А) вводится в другой класс (класс В)...

Как получить доступ к полям класса, который в свою очередь является полем шаблонного класса?
В данном случае параметром шаблона функции является класс матрица, в arr находится сама матрица. Необходимо инициализировать arr (сделать...

Доступ к полям класса
Здравствуйте. Есть некий "интерфейс" Interface.h class Interface { protected: string role; // admin or user

20
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 16:53
Такое будет работать если Vector будет классом, а не UDT и в таком случае все действия можно упаковать в методы. Можно сделать LightWeight класс вектор который будет достаточно быстрым и занимать на 8 байт больше чем обычный UDT и с нужными методами.
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 18:35  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Такое будет работать если Vector будет классом
Ну... это ж простейший пример, а в реальности это - вся математика DX9, где вектора 2-3-4-хмерные, на них завязаны матрицы, в некоторых местах это очень чувствительно к быстродействию, например, в расчёте частиц. Я наоборот подумываю, что придётся отказаться от математики в виде исходника на VB в пользу dll, скомпилированной из SDK с SSE оптимизацией.
А в конкретном текущем проекте я, видимо, откажусь от класса для игрока в пользу структуры, переделка минимальная - просто собрать параметры игрока в структуру, задавать массив игроков, работать с ними по индексу.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 18:38
Mikle Quits, можно обернуть структуру в класс и юзать ее. Вот то что я писал про LightWeight
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 18:44  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
можно обернуть структуру в класс и юзать ее
Понимаю, но я же написал про объём математики, про чувствительность к быстродействию, да и к объёму.
А там и ещё подводные камни появятся, сейчас массив структур с векторами, матрицами и т. п. - это, при желании, готовый вертексный буфер, в случае же классов это окажется массив указателей на данные в куче.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 18:47
Mikle Quits, я имел в виду структуру игрока засунуть в объект. Можно будет где нужно юзать UDT, а в нужном месте класс.
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 19:00  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
структуру игрока засунуть в объект
И как извне (ключевое слово) класса я задействую эту структуру? Например, пуля у меня умеет проверять коллизии с игроками, это простая векторная математика наподобие той, что в п.1. Я опять сталкиваюсь с проблемой при возврате значений через ByRef параметры.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 20:41
Mikle Quits, смотри есть 2 пути. Какой ты выберешь?
  1. Сделать Lightweight класс игрока.
  2. Смапить внутреннюю структуру внутри класса на массив.
В первом случае ты создаешь структуру UDT с полями игрока и просто делаешь особым образом оболочку. Когда тебе нужно - ты просто обращаешься к объекту как к структуре.
Во втором случае ты объявляешь структуру внутри класса, и у тебя есть метод который возвращает тебе массив где первым элементом идет структура (внутри объекта).
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 20:58  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Когда тебе нужно - ты просто обращаешься к объекту как к структуре.
А можно подробнее, каким таким особым образом делать оболочку, чтобы к объекту можно было как к структуре обратиться?
Цитата Сообщение от The trick Посмотреть сообщение
Во втором случае ты объявляешь структуру внутри класса, и у тебя есть метод который возвращает тебе массив где первым элементом идет структура
Оно же не заставит работать это:
Visual Basic
1
vAdd T.V, V1, V2
Первый аргумент процедуры vAdd - вектор, а не массив.

На всякий случай уточню. Я знаю несколько вариантов решения проблемы, в п.1 привёл один, в п.3 ещё один.
То есть свою задачу я решил, но параллельно возник вопрос, можно ли к структурам внутри классов иметь полноценный доступ извне по ссылке.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 21:01
Цитата Сообщение от Mikle Quits Посмотреть сообщение
можно ли к структурам внутри классов иметь полноценный доступ извне по ссылке.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Option Explicit
 
Private Const FADF_AUTO As Long = 1
 
Private Type SAFEARRAYBOUND
    cElements   As Long
    lLBound     As Long
End Type
 
Private Type SAFEARRAY1D
    cDims       As Integer
    fFeatures   As Integer
    cbElements  As Long
    cLocks      As Long
    pvData      As Long
    Bounds      As SAFEARRAYBOUND
End Type
 
Private Declare Sub MoveArray Lib "msvbvm60" _
                    Alias "__vbaAryMove" ( _
                    ByVal pDest As Long, _
                    ByRef Source As Any)
Private Declare Function ArrPtr Lib "msvbvm60" _
                         Alias "VarPtr" ( _
                         ByRef pSA() As Any) As Long
                         
Private m_tData     As TPlayer
Private m_tSAMap    As SAFEARRAY1D
 
Public Property Get X() As Long
    X = m_tData.lX
End Property
Public Property Let X(ByVal lValue As Long)
    m_tData.lX = lValue
End Property
 
Public Property Get Y() As Long
    Y = m_tData.lY
End Property
Public Property Let Y(ByVal lValue As Long)
    m_tData.lY = lValue
End Property
 
Friend Function InternalData() As TPlayer()
    MoveArray ArrPtr(InternalData), VarPtr(m_tSAMap)
End Function
 
Private Sub Class_Initialize()
 
    m_tSAMap.Bounds.cElements = 1
    m_tSAMap.cbElements = LenB(m_tData)
    m_tSAMap.cDims = 1
    m_tSAMap.fFeatures = FADF_AUTO
    m_tSAMap.pvData = VarPtr(m_tData)
    
End Sub
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Option Explicit
 
Private Sub Form_Load()
    Dim c   As CPlayer
    Dim t() As TPlayer
    
    Set c = New CPlayer
 
    c.X = 1
    c.Y = 2
 
    t = c.InternalData      ' // Можешь этот массив хранить - он всегда будет ссылаться на актуальные данные
    
    Debug.Print t(0).lX
    Debug.Print t(0).lY
    
    t(0).lX = 3
    t(0).lY = 4
    
    Debug.Print c.X
    Debug.Print c.Y
    
    c.X = 5
    c.Y = 6
    
    Erase t     '   // Если класс уничтожается раньше массива, иначе не нужно
    
End Sub
Visual Basic
1
2
3
4
5
Public Type TPlayer
    lX      As Long
    lY      As Long
    ' // ....
End Type
Вот массив t будет всегда ссылаться на данные структуры, т.е. является указателем. Можешь при создании 1 раз его инициализировать и все.
3
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 21:11  [ТС]
Не вижу описания типа TPlayer.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 21:56
Mikle Quits, добавил

Добавлено через 39 минут
Кстати доступ к Friend полям намного быстрее чем к Public.

Добавлено через 1 минуту
Если не боишься библиотек типов, можно еще ускорить.
2
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
09.08.2024, 22:23  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
добавил
Хм... красиво.
Цитата Сообщение от The trick Посмотреть сообщение
Кстати доступ к Friend полям намного быстрее чем к Public.
Не знал.
Цитата Сообщение от The trick Посмотреть сообщение
Если не боишься библиотек типов, можно еще ускорить.
Данную задачу я уже делаю без классов вообще, а вот, если, всё же, компилировать математику в dll, создание tlb под это будет полезным. Я знаю, что через tlb быстрее, чем через Declare.
0
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 23:07
Цитата Сообщение от Mikle Quits Посмотреть сообщение
Данную задачу я уже делаю без классов вообще, а вот, если, всё же, компилировать математику в dll, создание tlb под это будет полезным. Я знаю, что через tlb быстрее, чем через Declare.
Я имел в виду другое. Смотри приложенный проект (классы не используются, а объекты есть и очень быстрые):

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Sub Main()
    Dim cP1 As IPlayer
    Dim cP2 As IPlayer
    
    Set cP1 = CreatePlayer(1, 2)
    Set cP2 = CreatePlayer(3, 4)
    
    Debug.Print cP1.X, cP1.Y
    Debug.Print cP2.X, cP2.Y
    
    cP1.X = 10: cP1.Y = 20
    cP2.X = 30: cP2.Y = 40
    
    Debug.Print cP1.X, cP1.Y
    Debug.Print cP2.X, cP2.Y
    
    
End Sub
Скомпилированный код методов - совсем минимальный:



А насчет API объявленных в TLB, в большинстве случаев уже почти неактуально.
Вложения
Тип файла: zip LightWeight.zip (12.9 Кб, 3 просмотров)
2
Модератор
10046 / 3892 / 883
Регистрация: 22.02.2013
Сообщений: 5,846
Записей в блоге: 79
09.08.2024, 23:59
Цитата Сообщение от Mikle Quits Посмотреть сообщение
Не знал.
https://www.vbforums.com/showt... ost5567231

Добавлено через 6 минут
Цитата Сообщение от Mikle Quits Посмотреть сообщение
Данную задачу я уже делаю без классов вообще, а вот, если, всё же, компилировать математику в dll, создание tlb под это будет полезным. Я знаю, что через tlb быстрее, чем через Declare.
У меня есть Inline Assembler который из VB6 можно заюзать. Если не смущает написание на асме то можешь его использовать. Он работает в IDE и в скомпилированном виде. Вызовы идут напрямую без всяких замедлений.

Вот пример SSE с использованием Add-in'а.
2
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
10.08.2024, 08:33  [ТС]
SAFEARRAY я использовал и раньше, но через кучу PutMem GetMem, а, оказывается, есть готовое.
Я только MoveArray (__vbaAryMove) начал переваривать, а тут ещё куча полезной информации.
Благодарю.
0
1383 / 838 / 90
Регистрация: 08.02.2017
Сообщений: 3,511
Записей в блоге: 1
10.08.2024, 11:48
Цитата Сообщение от Mikle Quits Посмотреть сообщение
Я только MoveArray (__vbaAryMove) начал переваривать
Интересная функция, в vba наверное такой нету, хоть она и "vba" )
Можно, используюя этот патч The trick (упрощенный слегка), сделать обертку-пустышку для процедуры vAdd в которой аргументы указать как Long. И передавать аргументы в "обертку" в виде указателей, а с нее они будут переадресовываться на vAdd в нужном виде..

Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'Перенаправление вызова процедуры/функции AddrDst на AddrSrc
Public Sub MakeRedirect(ByVal AddrDst As Long, ByVal AddrSrc As Long)
    Dim InIDE As Boolean
 
    Debug.Assert MakeTrue(InIDE)
 
    If InIDE Then
        GetMem4 ByVal AddrDst + &H16, AddrDst
        GetMem4 ByVal AddrSrc + &H16, AddrSrc
    Else
        VirtualProtect AddrDst, 8, PAGE_EXECUTE_READWRITE, 0
    End If
 
    GetMem4 ByVal AddrSrc, ByVal AddrDst
End Sub
Вложения
Тип файла: zip ClassStruct.zip (3.2 Кб, 6 просмотров)
2
1383 / 838 / 90
Регистрация: 08.02.2017
Сообщений: 3,511
Записей в блоге: 1
10.08.2024, 15:28
Мне, кстати такой лайф-хак на ум пришел. Там этот патч все-время слетает при первой ide-шной компиляции, но его можно "реабилитировать" прямо в процедуре - "обертке"
Visual Basic
1
2
3
4
5
6
Private Sub vAddPtr(ByVal vOut As Long, ByVal vIn1 As Long, ByVal vIn2 As Long)
    'патч сбрасыается при первом выполнении кода в ide (после редактирования и ide-шной перекомпиляции)
    'но его можно можно "реабилитировать" прямо в багвовом месте
    MakeRedirect AddressOf vAddPtr, AddressOf vAdd
    vAddPtr vOut, vIn1, vIn2
End Sub
0
 Аватар для Mikle Quits
759 / 278 / 14
Регистрация: 21.01.2023
Сообщений: 397
11.08.2024, 11:10  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
сделать обертку-пустышку для процедуры vAdd в которой аргументы указать как Long
И каждому вектору заводить его двойника с адресом? Причём, ладно бы, если бы все вектора были статичны, завести для них pV однократно и пользоваться, но часто функция оперирует локальными векторами, заданными в ней самой или полученными через аргументы. И функций много, vAdd - это просто пример.
Нет. На практике это не пойдёт, хотя, конечно, демонстрирует возможности.
0
1383 / 838 / 90
Регистрация: 08.02.2017
Сообщений: 3,511
Записей в блоге: 1
12.08.2024, 01:45
Цитата Сообщение от Mikle Quits Посмотреть сообщение
На практике это не пойдёт, хотя, конечно, демонстрирует возможности.
Собственно в этом и был мой посыл ) Еще можно делать "трамплин", с помощью него можно подменять задекларированную (библиотечную) функцию на свою, и т.о. использовать в ней тип передачи аргумента ByVal/ByRef, As Any. Видел раньше ваш гоночный-симулятор 3D (недовершенный) на другом форуме, сделано было конено очень профессионально графика и физика, просто удивляет, что такое можно создавать на VB )
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.08.2024, 01:45
Помогаю со студенческими работами здесь

Доступ к полям класса
Имеет список list с объектами класса zapis list<zapis> list как мне получить значение поля класса, например поле Number

Доступ к полям внешнего класса
Доброй ночи! Проблема в следующем, есть классы А и Б: class A{ private B } class B{ public foo(){ //хочу получить доступ к...

Доступ к полям родительского класса
Возможно, очень нубский вопрос, но у меня есть класс А и наследуемый от него класс В public class A { int a = 5; } ...

Доступ к полям у класса-наследника
есть следующая иерархия классов: abstract class A { bool flag; } class B:A { }

Доступ к private полям класса
Есть класс Student и список list который заполняется экземплярами класса. Потом этот список сортируем по росту ( обращаюсь к полю growth ),...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru