В общем сабж...Хотел поизвращаться на С++, писать маленький код, а тут столько подводных камней) Как вызвать конструктор? или сделать свой new?
IMHO, проще написать свою CRT с учётом требования малого объёма кода... или вообще делать всё а-ля C.
Например, можно сделать так: Код (Text): #include "libcpptiny.h" #include <windows.h> // ////////////////////////////////////////////// // Function definitions // Initialization //! All initializations (atexit table, constructors) void cpplibtiny_init(); //! C++ initializers (constructors) call void cpplibtiny_call_constructors(); // Deinitialization //! All deinitializations (destructors, atexit list) void cpplibtiny_deinit(); //! Terminators call void cpplibtiny_call_terminators(); //! Deinitialization of atexit list void cpplibtiny_destroy_atexit_table(); // Utilities //! Pointer to a function typedef void (__cdecl * cpplibtiny_funcptr) (); //! Pointer to a function typedef int (__cdecl * cpplibtiny_funcptr_int) (); //! Calls all functions from the table void cpplibtiny_call_func_table ( cpplibtiny_funcptr * begin, cpplibtiny_funcptr * end); //! Calls all functions from the table in a reverse order void cpplibtiny_call_func_table_rev ( cpplibtiny_funcptr * begin, cpplibtiny_funcptr * end); // ////////////////////////////////////////////// // Data // C++ initializers #pragma data_seg(".CRT$XCA") static cpplibtiny_funcptr cpplibtiny_init_begin[] = { 0 }; #pragma data_seg(".CRT$XCZ") static cpplibtiny_funcptr cpplibtiny_init_end[] = { 0 }; #pragma data_seg() // Terminators (atexit table) static cpplibtiny_funcptr * cpplibtiny_term_begin, * cpplibtiny_term_end; // ////////////////////////////////////////////// // Initialization void cpplibtiny_init() { cpplibtiny_call_constructors(); } void cpplibtiny_call_constructors() { cpplibtiny_call_func_table (cpplibtiny_init_begin, cpplibtiny_init_end); } // ////////////////////////////////////////////// // Deinitialization void cpplibtiny_deinit() { cpplibtiny_call_terminators(); cpplibtiny_destroy_atexit_table(); } void cpplibtiny_call_terminators() { cpplibtiny_call_func_table_rev (cpplibtiny_term_begin, cpplibtiny_term_end); } void cpplibtiny_destroy_atexit_table() { if (cpplibtiny_term_begin) delete [] cpplibtiny_term_begin; } // ////////////////////////////////////////////// // Utilities void cpplibtiny_call_func_table ( cpplibtiny_funcptr * begin, cpplibtiny_funcptr * end) { if (begin) for (; begin < end; ++begin) if (*begin) (*begin) (); } void cpplibtiny_call_func_table_rev ( cpplibtiny_funcptr * begin, cpplibtiny_funcptr * end) { if (begin) for (--end; begin <= end; --end) if (*end) (*end) (); } // ////////////////////////////////////////////// // atexit extern "C" int __cdecl atexit (void (__cdecl * func) () ) { // create atexit table if need if (!cpplibtiny_term_begin) cpplibtiny_term_begin = cpplibtiny_term_end = (cpplibtiny_funcptr*) new cpplibtiny_funcptr [1000]; // push the function into the list *cpplibtiny_term_end++ = func; return 0; } // ////////////////////////////////////////////// // Memory (de)allocation void * operator new (unsigned size) { return GlobalAlloc (0, size); } void operator delete (void * ptr) { GlobalFree (ptr); } // ////////////////////////////////////////////// // Program entry point //! Program entry point void cpplibtiny_main() { // do initializations cpplibtiny_init(); // execute user's code extern int main(); int main_ret = main(); // do deinitializations cpplibtiny_deinit(); ExitProcess (main_ret); } P.S. Код мой, хотя и подозрительно похож на LIBCTINY
Rustem За это отвечает компилятор и CRT. Тонкостей не знаю, но при определении статического объекта компилятор добавляет в специальную таблицу ссылку на вызов конструктора, а сами вызовы происходят при инициализации программы.
Rustem Хм.. Под CRT я имел ввиду библиотеку поддержки С++. Она включает в себя поддержку как С, так и С++. Просто не знаю, как по-другому её назвать.
Rustem Добавь мой код в проект (можно отдельным файлом), и конструкторы и деструкторы глобальных объектов будут запускаться сами. (только нужно entry_point поменять на cpplibtiny_main). Подробности, на чём основан этот код, есть в MSDN - ищи по "LIBCTINY".
Очень вкратце можно так: если мы напишем Код (Text): #pragma data_seg(".CRT$XCA") static cpplibtiny_funcptr cpplibtiny_init_begin[] = { 0 }; #pragma data_seg(".CRT$XCZ") static cpplibtiny_funcptr cpplibtiny_init_end[] = { 0 }; #pragma data_seg() то массив cpplibtiny_init_begin будет содержать указатели на функции - конструкторы глобальных объектов. Размер этого массива определяется с помощью второго указателя cpplibtiny_init_end. Теперь достаточно просто пройтись по этому массиву и вызвать все функции из него (пропуская нулевые указатели). Имена переменным cpplibtiny_init_begin и cpplibtiny_init_end, естественно, можно давать любые, важно то, в какой секции они находятся. Первая переменная находится в секции .CRT и подсекции XCA, а вторая переменная - в подсекции XCZ. Где-то между ними (по-моему, в XCP) находится массив указателей на конструкторы - туда его кладёт компилятор. Фишка в том, что линкер сортирует подсекции по именам по алфавиту, т.е. массив указателей окажется обязательно между нашими указателями. Ну а с деструкторами всё аналогично.