Есть класс CTEST: Код (Text): class COBJECT { public: virtual ~COBJECT(){}; }; class CTEST: public COBJECT { public: virtual void func() { ........... } }; Есть функции: Код (Text): extern "C" __declspec(dllexport) void NewObj(CTEST **ppNewObj) { *ppNewObj = new CTEST; } extern "C" __declspec(dllexport) void DeleteObj(CTEST *pObj) { if(pObj) delete pObj; } Всё это компилируется в библиотеку (dll). В другой программе (exe): Код (Text): #pragma comment(lib, "Test.lib") class COBJECT { public: virtual ~COBJECT(); }; class CTEST: public COBJECT { public: virtual void func(); }; extern "C" __declspec(dllimport) void NewObj(CTEST **ppNewObj); extern "C" __declspec(dllimport) void DeleteObj(CTEST *pObj); Далее тут идёт ошибка: Код (Text): class CMYTEST: public CTEST { public: int SomeValue; } .............. void main() { CMYTEST *a = NULL; NewObj((CTEST **)&a); a->SomeValue = 5; // <-- ошибка } Т.е. получается, что при вызове функции new() в dll-ке, выделяется память под базовый класс, а под SomeValue не выделяется, поэтому при записи a->SomeValue = 5 может возникнуть ошибка типа "память не может быть write" Что можно сделать? Я тут подумал, а что, если сделать так (в DLL): Код (Text): extern "C" __declspec(dllexport) void NewObj(CTEST **ppNewObj) { // Если память уже выделена в exe, то if(*ppNewObj) { // Создаём объект CTEST obj; // Копируем его поля (чтобы и указатель на таблицу виртуальных // функций скопировался) memcpy(*ppNewObj, &obj, sizeof(obj); // Выходим return; } *ppNewObj = new CTEST; } В exe-шнике: Код (Text): template <class DATA_TYPE> DATA_TYPE *New(DATA_TYPE **Data) { *Data = (DATA_TYPE *)new BYTE[sizeof(DATA_TYPE)]; return *Data; } class CMYTEST: public CTEST { public: int SomeValue; } .............. void main() { CMYTEST *a = NULL; New(&a); NewObj((CTEST **)&a); a->SomeValue = 5; // <-- ошибки быть не должно DeleteObj(a); } Но потом понял, что всё равно это неправильно, т.к. возникает ошибка при удалении: delete (в dll-ке) думает, что удаляется класс, а на самом деле удаляется массив байтов, а из-за скрытой передачи параметров, расположенных до хранящегося в указателе адреса, вознивает ошибка. Т.е. мне ужно начать удалять массив байтов, но тогда не будет вызываться деструктор. Что делать?? Помогите!
Pasha 111 Т.е. получается, что при вызове функции new() в dll-ке, выделяется память под базовый класс, а под SomeValue не выделяется Так и должно быть. А если у потомка три базовых класса, то они должны знать друг о друге, т.е. конструктор любого из них резервировать память под каждого родителя и потомка? А если потомок является продуктом иерархии классов? Как только тебе в голову могло придти, что класс-родитель может знать о классах-потомках. Копируем его поля (чтобы и указатель на таблицу виртуальных функций скопировался) Ты бы еще про указатель на таблицу не виртуальных методов вспомнил. Итого: Так на С++ программы не пишут.
q_q Ну дык а что делать-то???? У меня есть класс CDIALOG, CBUTTON, CEDIT и т.д. Я хочу сделать класс CDIALOG1: Код (Text): class CDIALOG1: public CDIALOG { public: CBUTTON *Button1; CBUTTON *Button2; CBUTTON *Button3; CEDIT *Edit1; CEDIT *Edit2; } *Dialog1; Но не могу из-за описанной выше проблемы (
Pasha 111 что делать-то? Прочитай букварь по С++. не могу из-за описанной выше проблемы Не можешь, потому что четкого представления о С++ не имеешь.
Pasha 111 Лучше переформулируй вопрос. Скажи в двух словах, чего надо сделать, а не вываливай свой код.
ОФФТОП volodya да и за ругательства предупреждения надо давать ( правила форума видимо он не читал ) Ведь даже в топе Тиро против Джоеля .. там нет не единого ругательства .. все культурно общались .. Pasha 111 Используй COM подход ..
volodya Мне нужно, чтобы в DLL-ке был класс, были функции по созданию и удалению, а в exe-шнике можно было бы делать наследование от этого класса. TermoSINteZ Что ты имеешь ввиду?
Pasha 111 помочь-то ведь сам не можешь Написать за тебя код? Рассказать тебе, что необходимо написать конструктор для CDIALOG1 и обеспечить в нем вызов конструктора CDIALOG и конструкторов CBUTTON'ов и CEDIT'ов и то же самое проделать в деструкторе? Мне нужно, чтобы в DLL-ке был класс Без dll'ки ты можешь создать требуемую иерархию? Других обс#рать все могут Не суди по себе.
q_q необходимо написать конструктор для CDIALOG1 и обеспечить в нем вызов конструктора CDIALOG и конструкторов CBUTTON'ов и CEDIT'ов и то же самое проделать в деструкторе? Это я и хотел сказать ... Если ты хочешь чтоб это все вызывалось и ДЛЛ.. то помоему будет глупо в нее вставлять описание классов .. но функции экспортировать все же можешь
Pasha 111 Ты сам понимаешь, что делаешь ? Что это за опус ? Код (Text): CMYTEST *a = NULL; NewObj((CTEST **)&a); Если тебе нужен экземпляр класса CMYTEST, то и New должен вызываться для CMYTEST, а не для предка CTEST. А у тебя же создается именно CTEST, в котором никакого поля SomeValue просто нет. С С++ я не в ладах, но в паскале для подобных случаев существует тип class-reference, т.е. ссылка на класс (точнее на тип класса). Если процедура должна создавать объекты разных типов, то ей дополнительно передается ссылка на создаваемый класс и она создает объект именно того класса, какой нужен. ИМХО нечто подобное должно быть и в С++. PS знатокам С++: иногда проще дать подсказку и закрыть тему, чем разводить дискуссии, переходящие в "ругательства"
q_q Понимаешь в чём дело, конструктор класса CDIALOG1 всё равно не вызывается: если я создаю объект через "new BYTE[sizeof(CDIALOG1)]", то сам понимаешь, а если писать "new CDIALOG1", то будет ошибка при компиляции, т.к. оператор new захочет положить в создаваемый объект таблицу виртуальных функций, но он их не знает, т.к. они в dll-ке лежат, поэтому будет куча ошибок unresolved external simbol... Да. Если всё в одном ехе, то всё работает. А при разносе функций получается то, что я написал выше. TermoSINteZ Опять не понял (не тупой) Ты имеешь ввиду экспортировать функции классов отдельно как самостоятельные функции, а потом самому заполнить все указатели на функции в объекте класса? leo Я это всё ПРЕКРАСНО понимаю! ПОЧЕМУ у меня не получается я понял ещё до того, как пост создал, а вот как исправить - не знаю.
leo Ну дык и чего постить? Pasha 111 По поводу экспортирования классов, посмотри аттач, может оно. 2139391200__Cpp.rar