powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Наткнусь ли я на баг, при таком подходе?
6 сообщений из 6, страница 1 из 1
Наткнусь ли я на баг, при таком подходе?
    #32688975
MySQLdb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть две структуры следующего вида

Код: plaintext
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.
 //Тип выбранного узла 
typedef enum   TreeNodeType {TreeNodeTypeRoot =  0 ,TreeNodeTypeENTERPRISE =  1 ,TreeNodeTypeSUBDIVISION =  2 ,TreeNodeTypePERSONNEL =  3 ,TreeNodeTypePERSONA =  4 ,TreeNodeTypeTEST =  5 , TreeNodeTypeTitle =  6  } NodeType;



 //Данные узла подразделения 
typedef struct TreeNodeDataSUBDIVISION
                            {

                               NodeType      cNodeType; //Тип узла списка 
                               long          nSUBDIV_ID; //Уникальный индекс подразделения. 
                               AnsiString    nSUBDIV_NAME; //Название подразделения. 
                               AnsiString    nSUBDIV_SCROOT; //Путь к каталогу сценариев. 
                               AnsiString    nSUBDIV_RZROOT; //Путь к каталогу результатов. 
                               long          nENTRPRS_ID; //Уникальный индекс предприятия. 
                            }
                            NodeDataSUBDIVISION;
                            typedef NodeDataSUBDIVISION *PNodeDataSUBDIVISION;


 //Данные узла пользователей 
typedef struct TreeNodeDataPERSONNEL
                            {

                               NodeType    cNodeType; //Тип узла списка 
                               long        nPERSON_ID; //Уникальный индекс пользователя. 
                               AnsiString  nPERSON_FIO; //Фамилия пользователя. 
                               AnsiString  nPERSON_POST; //Занимаемая должность. 
                               AnsiString  nPERSON_PASSWORD; //Пароль пользователя. 
                               bool        nPERSON_PROFILE; //Обучение по данной специальности профилирующее? 
                               long        nSUBDIV_ID; //Уникальный индекс подразделения. 

                            }
                            NodeDataPERSONNEL;
                            typedef NodeDataPERSONNEL *PNodeDataPERSONNEL;




в своей программе я использую TTreeView, в который заношу данные
через создание узла-объекта. в таком виде

Код: plaintext
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.
                                    //создаем объект TBL_SUBDIVISION 
                                   NodeDataSUBDIVISIONPtr = new(NodeDataSUBDIVISION);  //выделяем память 
                                   NodeDataSUBDIVISIONPtr->cNodeType = TreeNodeTypeSUBDIVISION;  //подразделение 
                                   NodeDataSUBDIVISIONPtr->nSUBDIV_ID = locADOQuery->Fields->Fields[ 0 ]->AsInteger;  //поле SUBDIV_ID 
                                   NodeDataSUBDIVISIONPtr->nSUBDIV_NAME = locADOQuery->Fields->Fields[ 1 ]->AsString;  //поле SUBDIV_NAME 
                                   NodeDataSUBDIVISIONPtr->nSUBDIV_SCROOT = locADOQuery->Fields->Fields[ 2 ]->AsString;  //поле SUBDIV_SCROOT 
                                   NodeDataSUBDIVISIONPtr->nSUBDIV_RZROOT = locADOQuery->Fields->Fields[ 3 ]->AsString;  //поле SUBDIV_RZROOT 
                                   NodeDataSUBDIVISIONPtr->nENTRPRS_ID = - 1 ;  //locADOQuery->Fields->Fields[4]->AsInteger; //поле ENTRPRS_ID 

                                    //добавляем узел 
                                   pItemCurr = locAdminTreeView->Items->AddChildObject(pItemRoot,(NodeDataSUBDIVISIONPtr->nSUBDIV_NAME),NodeDataSUBDIVISIONPtr);
                                   pItemCurr->ImageIndex =  6 ;
                                   pItemCurr->SelectedIndex =  7 ;
                                   pItemCurr->StateIndex = - 1 ;

                                    //освобождаем память 
                                   NodeDataSUBDIVISIONPtr = NULL;
                                   delete(NodeDataSUBDIVISIONPtr);



                                   //создаем объект TBL_PERSONNEL 
                                                                   NodeDataPERSONNELPtr = new(NodeDataPERSONNEL);
                                                                   NodeDataPERSONNELPtr->cNodeType = TreeNodeTypePERSONNEL; //Обучаемые 
                                                                   NodeDataPERSONNELPtr->nPERSON_ID =       locADOQuery->Fields->Fields[ 0 ]->AsInteger; //Уникальный индекс пользователя. 
                                                                   NodeDataPERSONNELPtr->nPERSON_FIO =      locADOQuery->Fields->Fields[ 1 ]->AsString; //Фамилия пользователя. 
                                                                   NodeDataPERSONNELPtr->nPERSON_POST =     locADOQuery->Fields->Fields[ 2 ]->AsString; //Занимаемая должность. 
                                                                   NodeDataPERSONNELPtr->nPERSON_PASSWORD = locADOQuery->Fields->Fields[ 3 ]->AsString; //Пароль пользователя. 
                                                                   NodeDataPERSONNELPtr->nPERSON_PROFILE =  locADOQuery->Fields->Fields[ 4 ]->AsBoolean; //Обучение по данной специальности профилирующее? 
                                                                   NodeDataPERSONNELPtr->nSUBDIV_ID =       locADOQuery->Fields->Fields[ 5 ]->AsInteger; //Уникальный индекс подразделения. 

                                                                    //добавляем узел 
                                                                   pItem = locAdminTreeView->Items->AddChildObject(pItemCurr,(NodeDataPERSONNELPtr->nPERSON_FIO),NodeDataPERSONNELPtr);
                                                                   pItem->ImageIndex =  10 ; //картинка пассивного узла 
                                                                   pItem->SelectedIndex =  12 ;  //картинка выбранного узла 
                                                                   pItem->StateIndex =  - 1 ;  //статус узла 

                                                                    //освобождаем память 
                                                                   NodeDataPERSONNELPtr = NULL; //освободили указатель 
                                                                   delete(NodeDataPERSONNELPtr);//и удалили его

Все хорошо при наполнении, а при работе столкнулся с такой проблемой:
при клике по узлу, в обработчике onChange, получаю ссылку на выбранный узел TTreeNode * Node, а через нее ссылку на данные (Node->Data) типа
void *.
В каждой структуре сидит поле , определяющее тип данных в узле,
для того, чтобы можно было корректно данные извлечь

Код: plaintext
NodeType      cNodeType;//Тип узла списка

проблема в том, что получив адрес на данные в момент выделения узла,
я фактически знаю что они там есть, но не знаю, как их проинтерпретировать,
используя конструкцию вида

Код: plaintext
1.
2.
3.
4.
переменная = PNodeDataSUBDIVISION(Node->Data)->поле из структуры

или

переменная = PNodeDataPERSONNEL(Node->Data)->поле из структуры

так как незннаю, какова вида структура там сидит, фактически имея только адрес. То есть я пологал, что в момент выделения узла, я смогу узнать какие данные в нем сидят, применив конструкцию типа


Код: plaintext
1.
2.
3.
4.
тип узла = PNodeDataSUBDIVISION(Node->Data)->cNodeType

или

тип узла = PNodeDataPERSONNEL(Node->Data)->cNodeType

Вот такая получилась неодназначность, которую попытался решить двумя способами. Первый по легкому пути, взял создал одну структуру, которая вместила в себя все поля двух выше перечисленных


Код: plaintext
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.
typedef struct TreeNodeData
                       {
                           //Тип узла? 
                          NodeType    cNodeType; //Тип узла 

                           //Данные  узла-заголовка 
                           //Данные корневого узла 
                           //NodeType    cNodeType;//Тип узла списка 
                          AnsiString  Title; //Заголовок узла 

                           //Данные узла предприятия 
                           //NodeType    cNodeType;//Тип узла списка 
                          long        nENTRPRS_ID; //Уникальный индекс предприятия. 
                          AnsiString  nENTRPRS_NAME; //Название предприятия. 
                          long        nENTRPRS_COUNT; //Количество подразделений. 


                           //Данные узла подразделения 
                           //NodeType      cNodeType;//Тип узла списка 
                          long          nSUBDIV_ID; //Уникальный индекс подразделения. 
                          AnsiString    nSUBDIV_NAME; //Название подразделения. 
                          AnsiString    nSUBDIV_SCROOT; //Путь к каталогу сценариев. 
                          AnsiString    nSUBDIV_RZROOT; //Путь к каталогу результатов. 
                           //long          nENTRPRS_ID;//Уникальный индекс предприятия. 

                           //Данные узла пользователей 
                           //NodeType    cNodeType;//Тип узла списка 
                          long        nPERSON_ID; //Уникальный индекс пользователя. 
                          AnsiString  nPERSON_FIO; //Фамилия пользователя. 
                          AnsiString  nPERSON_POST; //Занимаемая должность. 
                          AnsiString  nPERSON_PASSWORD; //Пароль пользователя. 
                          bool        nPERSON_PROFILE; //Обучение по данной специальности профилирующее? 
                           //long        nSUBDIV_ID;//Уникальный индекс подразделения. 

                           //Данные узла персонала 
                           //NodeType    cNodeType;//Тип узла списка 
                          long        nPERSON_PID; //Уникальный индекс пользователя. 
                           //AnsiString  nPERSON_FIO;//Фамилия пользователя. 
                           //AnsiString  nPERSON_POST;//Занимаемая должность. 
                           //AnsiString  nPERSON_PASSWORD;//Пароль пользователя. 
                           //long        nSUBDIV_ID;//Уникальный индекс подразделения. 

                           //Данные узла теста 
                           //NodeType    cNodeType;//Тип узла списка 
                          long        nTEST_ID; //Уникальный индекс трека отчета. 
                          AnsiString  nTEST_METHOD; //Метод тестирования. 
                          AnsiString  nTEST_THEME; //Название темы опроса. 
                          TDateTime   nTEST_DATE; //Дата проведения опроса. 
                          TDateTime   nTEST_TIME; //Время проведения опроса. 
                          long        nTEST_SUMMARK; //Общее количество набранных баллов. 
                          long        nTEST_MAXMARK; //Максимально возможное количество баллов. 
                          AnsiString  nTEST_SELF; //Место хранения отчета. 
                           //long        nPERSON_ID;//Уникальный индекс пользователя. 

                       }
                       NodeData;
                       typedef NodeData *PNodeData;


неэкономично, но зато теперь я точно знаю, как проинтерпретировать данный,
и второй способ, по которому есть вопрос.

Во втором способе я зделал структуру вида

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 //Данные  котрольного узла 
typedef struct TreeNodeDataType
                            {

                               NodeType    cNodeType; //Тип узла списка 
                            }
                            NodeDataType;
                            typedef NodeDataType *PNodeDataType;

и в момен выделения узла, и получения ссылки на его данные,
прежде чем начать их обработку, я узнаю тип узла вот такой конструкцией

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
  TTreeNode* RootNode; //корневой узел 
   NodeType LocType; //тип узла 
   PNodeDataType  NodeDataTypePtr = NULL; //преобразование для типа узла 
 

     //Сначало освобождаем корневой узел 
    RootNode = AdminTreeView->Items->GetFirstNode();
    NodeDataTypePtr = PNodeDataType(RootNode->Data);
    LocType =  NodeDataTypePtr->cNodeType;

то есть такая как бы вольная интерпетация данных, исходя из того предположения,
что в памяти у меня две сструктуры двух типов, разных размеров,
но я знаю, что первым полем в каждой из них идет enum, который как я пологаю, должен занимать фиксированное количество байт и в первой и во второй структуре.

Вопрос в том, если я буду запускать программу на разных машинах,
с разными операционками, в которых может быть под enum отводится разное количество байт, скажем на одной 4, на другой 8, не загребу ли я таким подходим лишнию порцию байтов, в результате чего получу неправельную интерпретацию
Код: plaintext
cNodeType
, так как захвочу лишку информации?







-----------------------------------------------------------
С уважением,MySQLdb
...
Рейтинг: 0 / 0
Наткнусь ли я на баг, при таком подходе?
    #32689557
black zorro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошу прощения если неправильно понял
с чем-то похожим приходится часто сталкиваться и мне делаю выборки из бд
и строю дерево объектов.
делаю так: когда данных в узле мало или же эти поля почти одинаковы для
то использую ваш первый вариант с флажком признаком типа узла
Код: plaintext
1.
2.
3.
4.
5.
6.
 enum WhatIsHere { TT_FOO1 , TT_FOO2 , ...}
 struct Foo {
   WhatIsHere who_am_i;
   FooData1 foo1;  // поля для первого типа узла 
   FooData2 foo2; // поля для второго типа узла 
 };
в ситуации когда данные узлов сильно различаются я строю иерархию классов

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
 class FooFather {
   public:
    virtual do_some_work_for_this_node (void) =  0 ;
 };

 class Foo1 : public FooFather{
   FooData1 foo1;
   public:
    do_some_work_for_this_node (void){
      // some code  
    }
 };

 class Foo2 : public FooFather{
   FooData2 foo2;
   public:
    do_some_work_for_this_node (void){
      // some code  
    }
 };
во втором случае немного больше возни - но выше и контроль за кодом.
...
Рейтинг: 0 / 0
Наткнусь ли я на баг, при таком подходе?
    #32689599
Фотография Анатолий Широков
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во-первый, Вы ассоциируете данные с узлом дерева и сразу же эти данные удаляете - то есть Ваша программа получит Access Violation как только Вы попытаетесь разименованить данные:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
    //создаем объект TBL_SUBDIVISION 
   NodeDataSUBDIVISIONPtr = new(NodeDataSUBDIVISION);  //выделяем память 
   NodeDataSUBDIVISIONPtr->cNodeType = TreeNodeTypeSUBDIVISION;  //подразделение 
   NodeDataSUBDIVISIONPtr->nSUBDIV_ID = locADOQuery->Fields->Fields[ 0 ]->AsInteger;  //поле SUBDIV_ID 
   NodeDataSUBDIVISIONPtr->nSUBDIV_NAME = locADOQuery->Fields->Fields[ 1 ]->AsString;  //поле SUBDIV_NAME 
   NodeDataSUBDIVISIONPtr->nSUBDIV_SCROOT = locADOQuery->Fields->Fields[ 2 ]->AsString;  //поле SUBDIV_SCROOT 
   NodeDataSUBDIVISIONPtr->nSUBDIV_RZROOT = locADOQuery->Fields->Fields[ 3 ]->AsString;  //поле SUBDIV_RZROOT 
   NodeDataSUBDIVISIONPtr->nENTRPRS_ID = - 1 ;  //locADOQuery->Fields->Fields[4]->AsInteger; //поле ENTRPRS_ID 

    //добавляем узел 
   pItemCurr = locAdminTreeView->Items->AddChildObject(pItemRoot,(NodeDataSUBDIVISIONPtr->nSUBDIV_NAME),NodeDataSUBDIVISIONPtr);
   pItemCurr->ImageIndex =  6 ;
   pItemCurr->SelectedIndex =  7 ;
   pItemCurr->StateIndex = - 1 ;

    //освобождаем память 
   NodeDataSUBDIVISIONPtr = NULL;
  delete(NodeDataSUBDIVISIONPtr);

Освобождать данные Вам надо по закрытию приложения.

Второе, чтобы гарантировать размер enum используется такая техника:

Код: plaintext
typedef enum   TreeNodeType {TreeNodeTypeRoot = int( [b]0 )[/b], TreeNodeTypeENTERPRISE =  1 ,TreeNodeTypeSUBDIVISION =  2 ,TreeNodeTypePERSONNEL =  3 ,TreeNodeTypePERSONA =  4 ,TreeNodeTypeTEST =  5 , TreeNodeTypeTitle =  6  } NodeType;

Удачи!
...
Рейтинг: 0 / 0
Наткнусь ли я на баг, при таком подходе?
    #32689615
MySQLdb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда вопрос такого плана:

допустим я делаю так

typedef struct STname
{
...............
} ForType;//некая структура

typedef ForType* PForType; //указатель на эту структуру

я как и описывал, через new заполняю ее данными, и подвязываю к узлу.
Есть ли какой нибуть способ, фактически имея void* на эти данный
посредством (Node->Data), узнать програмно, что там сидит структура,
имя которой STName. ?????


И еще вопрос, структуры могут быть вложенными? К примеру


typedef struct STname
{
...............
} ForType;//некая структура

typedef struct STname1
{
ForType StructInStruct;

} ForType1;//некая структура


-----------------------------------------------------------
С уважением,MySQLdb
...
Рейтинг: 0 / 0
Наткнусь ли я на баг, при таком подходе?
    #32689660
Фотография Анатолий Широков
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторЕсть ли какой нибуть способ, фактически имея void* на эти данный
посредством (Node->Data), узнать програмно, что там сидит структура,
имя которой STName. ????
нет, для этого Вы и ввели поле типа.


авторИ еще вопрос, структуры могут быть вложенными? К примеру

У Вас не структуры вложены, а структура содержит другую структуру в качестве члена данных. Вложенные структуры это:

Код: plaintext
1.
2.
3.
4.
struct foo
{
    struct boo {};
    foo data;
};

Прислушайтесь к совету black_zorro и используйте полиморфизм (второй пример автора), тогда поле типа Вам не понадобится.
...
Рейтинг: 0 / 0
Наткнусь ли я на баг, при таком подходе?
    #32689825
MySQLdb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторПрислушайтесь к совету black_zorro и используйте полиморфизм (второй пример автора), тогда поле типа Вам не понадобится

Это значит мне надо для определенного типа узла сделать для него класс,
указав в нем поля, а затем создать экземпляр этого класса, получив на него
указатель, и этот указатель поместить в TreeNode ->Data?

а как к примеру тогда будет выглядеть вызов функции

do_some_work_for_this_node (void){
// some code
}

через (Node->Data) ???

-----------------------------------------------------------
С уважением,MySQLdb
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Наткнусь ли я на баг, при таком подходе?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]