Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
#1

Преобразование классов - C++

24.04.2014, 16:06. Просмотров 792. Ответов 11
Метки нет (Все метки)

Есть код для MS VS C++, который переписываю на другой ЯП и не совсем понимаю как преобразовываются объекты.
Интересующие части кода. Классы.
C++
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class IACTIVEMODEL
 { public:
      virtual VOID initialize (ICOMPONENT *cpt) = 0;
      virtual ISPICEMODEL *getspicemodel (CHAR *primitive) = 0;
      virtual IDSIMMODEL  *getdsimmodel (CHAR *primitive) = 0;
      virtual VOID plot (ACTIVESTATE state) = 0;
      virtual VOID animate (INT element, ACTIVEDATA *newstate) = 0;
      virtual BOOL actuate (WORD key, INT x, INT y, DWORD flags) = 0;
 };
 
class IDSIMMODEL
 { public:
      virtual INT  isdigital (CHAR *pinname) = 0;
      virtual VOID setup (IINSTANCE *instance, IDSIMCKT *dsim) = 0;
      virtual VOID runctrl (RUNMODES mode) = 0;
      virtual VOID actuate (REALTIME time, ACTIVESTATE newstate) = 0;
      virtual BOOL indicate (REALTIME time, ACTIVEDATA *newstate) = 0;
      virtual VOID simulate (ABSTIME time, DSIMMODES mode) = 0;
      virtual VOID callback (ABSTIME time, EVENTID eventid) = 0;
 };
 
class ISPICEMODEL
 { public:
      virtual INT  isanalog (CHAR *pinname) = 0;
      virtual VOID setup (IINSTANCE *, ISPICECKT *) = 0;
      virtual VOID runctrl (RUNMODES mode) = 0;
      virtual VOID actuate (REALTIME time, ACTIVESTATE newstate) = 0;
      virtual BOOL indicate (REALTIME time, ACTIVEDATA *newstate) = 0;
      virtual VOID dcload (REALTIME time, SPICEMODES mode, DOUBLE *oldrhs, DOUBLE *newrhs) = 0;
      virtual VOID acload (SPICEFREQ omega, DOUBLE *rhs, DOUBLE *irhs) = 0;
      virtual VOID trunc  (REALTIME time,  REALTIME *newtimestep) = 0;
      virtual VOID accept (REALTIME time, DOUBLE *rhs) = 0;
 };
 
class READOUTX : public IACTIVEMODEL, public IDSIMMODEL , public ISPICEMODEL
 {
    public:
      READOUTX (VOID);
      ~READOUTX (VOID);
      // Implementation of IACTIVEMODEL
      VOID initialize (ICOMPONENT *cpt);
      ISPICEMODEL *getspicemodel (CHAR *device);
      IDSIMMODEL *getdsimmodel (CHAR *device);
      VOID plot (ACTIVESTATE state);
      VOID animate (INT element, ACTIVEDATA *newstate);
      BOOL actuate (WORD key, INT x, INT y, DWORD flags);
 
      // IDSIMMODEL interface
            // Pin typing and connection functions:
      virtual INT isdigital (CHAR *pinname);
 
            // Common Functions:
      virtual VOID runctrl (RUNMODES mode);
      virtual VOID actuate (REALTIME time, ACTIVESTATE newstate);
      virtual BOOL indicate (REALTIME time, ACTIVEDATA *newstate);
            // Functions called by DSIM:
      VOID setup (IINSTANCE *, IDSIMCKT *dsim);
      VOID simulate (ABSTIME time, DSIMMODES mode);
      VOID callback (ABSTIME time, EVENTID eventid);
      ISIBLING *queryinterface (UINT iid);
 
      // ISPICEMODEL
      INT isanalog(CHAR *);
      VOID setup (IINSTANCE *, ISPICECKT *spice);
      VOID dcload(REALTIME, SPICEMODES, DOUBLE *, DOUBLE *);
      VOID acload(SPICEFREQ, DOUBLE *, DOUBLE *);
      VOID trunc(REALTIME, REALTIME *);
      VOID accept(REALTIME, DOUBLE *);
 
      VOID set_device(CHAR *s);
      VOID set_dprimitive(CHAR *s);     // primitive from DSIM
      VOID set_aprimitive(CHAR *s);     // primitive from SPICE
 
    private:
      ICOMPONENT *component;
      IINSTANCE *instance;
      IINSTANCE *ainstance;
      IDSIMCKT  *dsim;
      ISPICECKT *spice;
      IDEBUGPOPUP *idp;
      POINT textorg;
      HTEXTSTYLE textstyle;
      CHAR readout[10];
      CHAR device[32];
      CHAR dprimitive[32];
      CHAR aprimitive[32];
      CREATEPOPUPSTRUCT cps;
      DWORD i;
      IDSIMPIN  *pin_d0, *pin_d1, *pin_q;
      SPICENODE pin_plus, pin_minus;
      ACTIVEDATA adata;
 
      CHAR * EnumToString(INT element, ACTIVEDATA *data);
      CHAR * EnumToState(INT element, ACTIVEDATA *data);
      CHAR * EnumToRunCtrl(RUNMODES modes);
      CHAR * EnumToSmode(DSIMMODES smode);
      CHAR * DumpACTIVEDATA(INT element, ACTIVEDATA *data);
 
 };
Создание объекта.
C++
1
2
3
4
5
extern "C"  EXPORT IACTIVEMODEL *  createactivemodel (CHAR *device, ILICENCESERVER *ils)
 {
    READOUTX *model = new READOUTX();
    return (IACTIVEMODEL *) model;
 }
Преобразование объекта в другой.
C++
1
2
3
4
5
6
7
8
9
ISPICEMODEL *READOUTX::getspicemodel (CHAR *primitive)
{ 
    return (ISPICEMODEL *) this;
}
 
IDSIMMODEL *READOUTX::getdsimmodel (CHAR *primitive)
 {
    return (IDSIMMODEL *) this;
 }
В this находится тот указатель что был возвращен функцией createactivemodel(), но вот как он потом становится ISPICEMODEL или IDSIMMODEL?
Кстати, в createactivemodel() так же происходит преобразование в IACTIVEMODEL. Непонятно.

Как писал в начале, переписываю кода на другой ЯП и нужно знать как все это работает
Если просто передать this прога виснет или вылетает. Но если создать новый объект из ISPICEMODEL или IDSIMMODEL (в зависимости от функции), то все работает нормально. Как C++ преобразовывает один объект в другой?

Добавлено через 4 часа 50 минут
Никто не знает?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.04.2014, 16:06     Преобразование классов
Посмотрите здесь:

C++ иерархия классов
C++ Создание классов
Видимость классов C++
C++ Наследование классов.
Прототипы классов C++
Преобразование классов C++
C++ Лафоре, преобразование классов
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6854 / 4065 / 927
Регистрация: 30.01.2014
Сообщений: 6,862
24.04.2014, 16:28     Преобразование классов #2
Цитата Сообщение от locm Посмотреть сообщение
Как писал в начале, переписываю кода на другой ЯП и нужно знать как все это работает
Что за язык? Поддерживает ли он множественное наследование?

Цитата Сообщение от locm Посмотреть сообщение
Как C++ преобразовывает один объект в другой?
Получает смещение базы относительно наследника, возвращает адрес объекта нужного базового класса. По идее здесь явные касты вообще не нужны. Это одно из стандартных автоматических преобразований.
C++
1
2
3
4
5
6
7
8
ISPICEMODEL *READOUTX::getspicemodel (CHAR *primitive)
{ 
    return this;
}
IDSIMMODEL *READOUTX::getdsimmodel (CHAR *primitive)
{
    return this;
}
Цитата Сообщение от locm Посмотреть сообщение
Если просто передать this прога виснет или вылетает.
Просто this (т.е. без преобразования) передавать нельзя, потому что адреса объектов базовых классов и наследника при множественном наследовании не совпадают.

Цитата Сообщение от locm Посмотреть сообщение
Никто не знает?
Чтобы получить корректный ответ, нужно точнее сформулировать задачу. Что конкретно нужно сделать в этом другом ЯП? Если потребуется, то можно и код привести на этом другом ЯП.
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
24.04.2014, 17:14  [ТС]     Преобразование классов #3
Цитата Сообщение от DrOffset Посмотреть сообщение
Что за язык?
PureBasic.

Цитата Сообщение от DrOffset Посмотреть сообщение
Поддерживает ли он множественное наследование?
Он даже ООП не поддерживает, но это и не важно, т. к. код специфический и предназначен для компиляции в MS VS C++. В C++ Builder и MinGW компилируется, но не работает вылетая. Нужна полная бинарная совместимость с классами VS C++.
Цитата Сообщение от DrOffset Посмотреть сообщение
Получает смещение базы относительно наследника, возвращает адрес объекта нужного базового класса.
Смещение это понятно, но как тогда быть в приватным содержимым класса?

Цитата Сообщение от DrOffset Посмотреть сообщение
Просто this (т.е. без преобразования) передавать нельзя, потому что адреса объектов базовых классов и наследника при множественном наследовании не совпадают.
Это я уже понял (в ходе экспериментов). Поэтому хочу понять как устроен класс (какова его структура в скомпилированном виде) именно в VS C++.

Цитата Сообщение от DrOffset Посмотреть сообщение
Что конкретно нужно сделать в этом другом ЯП?
Нужно сэмулировать класс, полностью совместимый по структуре с аналогичным в VS C++, но для этого необходимо знать как располагаются данные в памяти.
Создаю DLL (что-то типа плагина), в которой создается объект и передается вызывающей программе.

В простейшем случае, класс эмулирую таким образом. Представим что имеется подобный класс.
C++
1
2
3
4
5
6
7
8
9
10
class IACTIVEMODEL
 { public:
      virtual VOID initialize (ICOMPONENT *cpt) = 0;
      virtual ISPICEMODEL *getspicemodel (CHAR *primitive) = 0;
 
  private:
      Int x;
      Int y;
 
 };
Эмулирую таким образом.
PureBasic
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
Structure ClassParam
  *vt ;pointer to virtual table as first entry 
  ; Приватные переменные класса.
  x.i
  y.i
EndStructure 
 
EnableASM
 
Procedure NEW()   ; Создание объекта.
  Protected *Class.ClassParam=0
  
  *Class = AllocateMemory(SizeOf(ClassParam)) 
  If *Class
    *Class\vt = ?ClassFunct
  EndIf   
  
  ProcedureReturn *Class
EndProcedure
 
Procedure initialize(*cpt.ICOMPONENT)
  Protected *This.ClassParam
  MOV *This, ecx
  
EndProcedure
 
Procedure.i getspicemodel(*sPrimitive)
  Protected *This.ClassParam
  MOV *This, ecx
  
  ProcedureReturn 0
EndProcedure
 
DataSection
  ClassFunct: ; Таблица методов класса.
  Data.i @initialize()
  Data.i @getspicemodel()
EndDataSection
В итоге получается объект, совместимый с скомпилированным кодом в VS C++.
Catstail
Модератор
22313 / 10718 / 1742
Регистрация: 12.02.2012
Сообщений: 17,792
24.04.2014, 17:20     Преобразование классов #4
Цитата Сообщение от locm Посмотреть сообщение
Он даже ООП не поддерживает
- а по Вашему коду этого не скажешь.
DrOffset
6854 / 4065 / 927
Регистрация: 30.01.2014
Сообщений: 6,862
24.04.2014, 17:28     Преобразование классов #5
Цитата Сообщение от locm Посмотреть сообщение
Поэтому хочу понять как устроен класс (какова его структура в скомпилированном виде) именно в VS C++.
Это задача не такая простая. Здесь нужно конкретизировать вплоть до версии компилятора и ключей компиляции.
Я бы не стал с этим связываться, ибо непереносимо. Даже в пределах одного компилятора.

Цитата Сообщение от locm Посмотреть сообщение
В итоге получается объект, совместимый с скомпилированным кодом в VS C++.
Если я правильно понял, то это нужно для того, чтобы потом передать этот объект в С++ код через вызов какой-либо функции? Если да, то есть более правильный и переносимый способ это сделать.
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
24.04.2014, 18:09  [ТС]     Преобразование классов #6
Цитата Сообщение от DrOffset Посмотреть сообщение
Это задача не такая простая. Здесь нужно конкретизировать вплоть до версии компилятора и ключей компиляции.
Версия 6. Какие ключи компиляции, не знаю. Но судя по всему значения по умолчанию, потому что нигде в инструкции о них ни слова. Написано "создать проект под DLL".

Цитата Сообщение от DrOffset Посмотреть сообщение
Я бы не стал с этим связываться, ибо непереносимо.
В случае одного класса (без необходимости преобразования из одного в другой) все нормально работает.
Если разделить класс на составные части (IACTIVEMODEL, IDSIMMODEL и ISPICEMODEL) и создавать отдельные объекты, то тоже работает, но тогда возникает проблема с приватными переменными, которые должны быть общими для классов.

Цитата Сообщение от DrOffset Посмотреть сообщение
нужно для того, чтобы потом передать этот объект в С++ код через вызов какой-либо функции? Если да, то есть более правильный и переносимый способ это сделать.
Да, объект создается в экспортируемой из DLL функции и передается вызывающей программе. То что это не совсем удачное решение - понятно, но программу не я писал.
DrOffset
6854 / 4065 / 927
Регистрация: 30.01.2014
Сообщений: 6,862
24.04.2014, 18:12     Преобразование классов #7
locm, так dll - на Basic?
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
24.04.2014, 18:17  [ТС]     Преобразование классов #8
Да.
Но программа судя по всему на VS C++. Ей нужно передать указатель на объект.
DrOffset
6854 / 4065 / 927
Регистрация: 30.01.2014
Сообщений: 6,862
24.04.2014, 18:34     Преобразование классов #9
Сообщение было отмечено автором темы, экспертом или модератором как ответ
locm, в общем я все-таки предлагаю практично подойти к вопросу и не идти по опасному пути. Хотя конечно можно, но тогда дизассемблер в помощь. Стандарт языка не регламентирует как именно будут располагаться данные в памяти, поэтому тут только самостоятельные исследования помогут.
Однако, есть способ куда прямее. Нужно создать еще одну dll, на C++. Интерфейсом у нее будет набор С-функций, которые предоставляют доступ к объектам.
Покажу на простом примере:
C++
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class A
{
public:
    void set_a(int a);
    int  get_a();
 
private:
    int a;
};
 
class B
{
public:
    void set_b(int b);
    int  get_b();
 
private:
    int b;
};
 
class C : public A, public B
{
public:
    void set_c(int c);
    int  get_c();
 
private:
    int c;
};
//create
extern "C" void * create_A()
{
    return new A();
}
extern "C" void * create_B()
{
    return new B();
}
extern "C" void * create_C()
{
    return new C();
}
//destroy
extern "C" void destroy_A(void * ptr)
{
    return delete static_cast<A*>(ptr);
}
extern "C" void destroy_B(void * ptr)
{
    return delete static_cast<B*>(ptr);
}
extern "C" void destroy_C(void * ptr)
{
    return delete static_cast<C*>(ptr);
}
 
// only for A
extern "C" int A_get_a(void * ptr)
{
    return static_cast<A*>(ptr)->get_a();
}
extern "C" void A_set_a(void * ptr, int a)
{
    return static_cast<A*>(ptr)->set_a(a);
}
//only for B
extern "C" int B_get_b(void * ptr)
{
    return static_cast<B*>(ptr)->get_b();
}
extern "C" void B_set_b(void * ptr, int b)
{
    return static_cast<B*>(ptr)->set_b(b);
}
//only for C
extern "C" int C_get_a(void * ptr)
{
    return static_cast<C*>(ptr)->get_a();
}
extern "C" void C_set_a(void * ptr, int a)
{
    return static_cast<C*>(ptr)->set_a(a);
}
extern "C" int C_get_b(void * ptr)
{
    return static_cast<C*>(ptr)->get_b();
}
extern "C" void C_set_b(void * ptr, int b)
{
    return static_cast<C*>(ptr)->set_b(b);
}
extern "C" int C_get_c(void * ptr)
{
    return static_cast<C*>(ptr)->get_c();
}
extern "C" void C_set_c(void * ptr, int c)
{
    return static_cast<C*>(ptr)->set_c(c);
}
Теперь эту dll можно подключить к dll на Basic и использовать эти функции для создания и установки свойств С++ объектов. Это стандартный подход, при решении подобных задач.
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
24.04.2014, 19:05  [ТС]     Преобразование классов #10
Спасибо, но не хотелось бы такой вариант, разве что если С-функции компилировать в статическую библиотеку (если получится).
DrOffset
6854 / 4065 / 927
Регистрация: 30.01.2014
Сообщений: 6,862
24.04.2014, 19:43     Преобразование классов #11
Цитата Сообщение от locm Посмотреть сообщение
Спасибо, но не хотелось бы такой вариант
Дело твое. Можно чуть упростить, если создание оберток над методами добавить в макрос(ы).

Цитата Сообщение от locm Посмотреть сообщение
разве что если С-функции компилировать в статическую библиотеку (если получится).
Статическую библиотеку подцепить в Basic? Получится, только если у него с С++ одинаковый линкер.

Добавлено через 1 минуту
locm, А вообще, обычно клиентское приложение (то, которое на С++) должно предоставлять все механизмы для оперирования необходимыми для него объектами. Ты уверен, что этого там нет уже?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.04.2014, 21:26     Преобразование классов
Еще ссылки по теме:

Преобразование пользовательских классов C++
C++ Шаблоны классов
C++ Взаимодействие классов
Наследование классов C++
Насследование классов C++

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

Или воспользуйтесь поиском по форуму:
locm
1979 / 734 / 70
Регистрация: 28.10.2011
Сообщений: 2,135
Записей в блоге: 2
24.04.2014, 21:26  [ТС]     Преобразование классов #12
Цитата Сообщение от DrOffset Посмотреть сообщение
Статическую библиотеку подцепить в Basic? Получится, только если у него с С++ одинаковый линкер.
Линкер должен подойти. Используется polink.exe из пакета Pelles C.

Цитата Сообщение от DrOffset Посмотреть сообщение
А вообще, обычно клиентское приложение (то, которое на С++) должно предоставлять все механизмы для оперирования необходимыми для него объектами.
Объект создается в DLL и взаимодействие программы с библиотекой осуществляется через него.
В принципе, с эмулировать объект не сложно. Трудности возникли именно при преобразовании классов.
Решил таким образом. Создал на каждый класс свою таблицу указателей на методы, вместо общей для всех методов. В зависимости от того, какого типа класс, выбирается соответствующая таблица, правда пришлось решать проблему с приватными переменными, которые должны быть общими для всех классов. Это тоже удалось, но пришлось создать под каждый класс свою структуру, с соответствующим смещением переменных от начала структуры.
Тестирование проблем не выявило. Все работает как должно и вылетов не наблюдается.
Yandex
Объявления
24.04.2014, 21:26     Преобразование классов
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru