Здравствуйте, Batiskaf, Вы писали:
B>Предложенный вами метод применялся и в МФС и во многих других библиотеках, регистрация на вызове конструктора статик поля, и если я помню, поднимались на форуме проблемы с некоректной инициализацией статик полей, кажется кто-то упоминал что компилятор не гарантирует конструирования статик поля до вызова кода, который не обращается напрямую к этому полю, другими словами, класс еще не пропишется в карточке, а в коде будет уже обращение к карточке, где будет искаться функция-создатель по имени класса.
Ну прриведи тогда конкретный пример, а то не очень понятно, что именно имеется ввиду. Вообще для решения проблемы создания некого статического объекта раньше других могу предложить примерно следующее.
В каком-то .cpp есть функция получения статического объекта, который должен быть сконструирован ранше других.
Далее, к каждому .cpp подключается примерно такой .h файл:
class TStaticIniter
{
public:
TStaticIniter(){GetStaticObject();}
};
static TStaticIniter static_object_initer;
При этом TObject будет создан гарантировано ранее других статических объектов, описанных после включения вышеприведенного хедера.
B>Также, при использовании такого метода регистрации совместно с компилятором Code Warior, возник совсем неожиданный трабл, компилятор категорически не хотел включать в исполняемый модуль объектник того класса, экземпляры которого явным образом не создаются в других объектниках, ведь функция создатель находится рядом с классом, в том же объектнике.
Здесь тоже без конкретного примера чего-то предложить сложно.Разве что сменить компилятор
B>Линкер не обнаруживал внешних ссылок на объектник, и тихонько его выкусывал. Может это и конфигурируется, незнаю. Как быть в таком случае. Так же я слышал что рассматривается предложение по приминению динамической загрузки С++ классов на момент необходимости ( понятия не имею как, кто бы просветил ), может вышеупомянутый трабл имеет непосредственное отношение к данному фичеру?
Вряд-ли И вообще "динамическая загрузка классов" в таком определении — нелепость какая-то. Может это про джаву было?
Здравствуйте, Vladik, Вы писали:
V>Ну прриведи тогда конкретный пример, а то не очень понятно, что именно имеется ввиду. Вообще для решения проблемы создания некого статического объекта раньше других могу предложить примерно следующее.
Мне казалось, я все нормально объяснил, ну да ладно.
Тут речь не идет об очередности инициализации статик полей, а говорится о моменте инициализации статик поля вообще. Ведь все что сказано в определении языка относительно статик поля, что в момент ИСПОЛЬЗОВАНИЯ этого поля компилятором гарантируется, что оно будет прежде инициализированно. И никто не гарантирует инициализацию поля ( и запуск тем самым конструктора класса ), которое не используется в коде этого класса вообще, либо используется например в каком то методе ( не в единственном конструкторе класса ).
Попытаюсь выразить это в коде, код конечно гипотетический, но на мой взгляд есть вероятность того что он не будет работать как ожидалось на каком то гипотетическом компиляторе Х:
/**********************************************
File main.cpp
**********************************************/#include"A.h"#include"B.h"int main(void)
{
const char* str = "class B";
cerr<< "string \""<<str<< (A::HaveString(str)? "\" ":" not ")<<"available in list"<<endl;
B().UseStaticField();
cerr<< "string \""<<str<< (A::HaveString(str)? "\" ":" not ")<<"available in list"<<endl;
return 0;
}
Так вот я о том, что результатом этой программы на мой взгляд не обязательно должен быть:
string "class B" available in list
string "class B" available in list
но может быть и так:
string "class B" not available in list
string "class B" available in list
Почему производитель компилятора не может делать такие припущения и не откладывать инициализацию статик поля на момент его использования, или не инициализировать поле вообще?
Что же касается CodeWarrior, мне кажется это продолжение той же темы:
На класс В нет внешних ссылок ( то-есть инстанс класса В не создается в других объектных модулях ), что мешает производителям компиляторов исключать объектный модуль класса В? Что по-этим двум вопросам говорит стандарт?
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Здравствуйте, Batiskaf, Вы писали:
B>Так вот я о том, что результатом этой программы на мой взгляд не обязательно должен быть:
Обязательно. Все "глобальные" статические переменные инициализируются до main().
[...] B>На класс В нет внешних ссылок ( то-есть инстанс класса В не создается в других объектных модулях ), что мешает производителям компиляторов исключать объектный модуль класса В? Что по-этим двум вопросам говорит стандарт?
Стандарт не говорит, что объектный модуль и класс как-то связаны. А исключить соответсвующую функцию мешает взятие и использование ее адреса. Так что это проблема твоего компилятора.
[...]
B>Также, при использовании такого метода регистрации совместно с компилятором Code Warior, возник совсем неожиданный трабл, компилятор категорически не хотел включать в исполняемый модуль объектник того класса, экземпляры которого явным образом не создаются в других объектниках, ведь функция создатель находится рядом с классом, в том же объектнике. Линкер не обнаруживал внешних ссылок на объектник, и тихонько его выкусывал. Может это и конфигурируется, незнаю. Как быть в таком случае.
Вообще — что-то загадочное. Попробуй а) объявить производящую функцию экспортируемой или б) сделать external-linkage функцию, в которую поместить вызов своей производящей функции (масло масляное, но уж шаманить — так шаманить).
Ну, например:
// MyMakeFunction() - производящая функцияextern"C"void _dummy(void) // подойдёт любой способ
{
MyMakeFunction();
}
В таком случае линкер не имеет права удалять _dummy и, соответственно, MyMakeFunction со всеми последствиями не будет удалена тоже.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
V>Обязательно.
В примере Batiskaf-а не обязательно:
// hdr.hclass A
{
public:
static A a;
};
// hdr.cpp
A A::a;
// main.cpp#include"hdr.h"// так вот здесь никаких гарантий относительно того, что а будет инициализирована
// именно так была поставлена проблема.
A test = A::a;
int main()
{
A b = A::a;
return 0;
}
Здравствуйте, Анатолий Широков, Вы писали:
V>>Обязательно. АШ>В примере Batiskaf-а не обязательно:
АШ>
АШ>// hdr.h
АШ>class A
АШ>{
АШ>public:
[ccode]
A &getA()
{
АШ> static A a;
return a;
}
АШ>};
АШ>// hdr.cpp АШ>A A::a;
АШ>// main.cpp АШ>#include "hdr.h"
АШ>// так вот здесь никаких гарантий относительно того, что а будет инициализирована АШ>// именно так была поставлена проблема. АШ>A test = A::a;
ГВ>Вообще — что-то загадочное. Попробуй а) объявить производящую функцию экспортируемой или б) сделать external-linkage функцию, в которую поместить вызов своей производящей функции (масло масляное, но уж шаманить — так шаманить).
ГВ>Ну, например:
ГВ>
ГВ>// MyMakeFunction() - производящая функция
ГВ>extern"C"void _dummy(void) // подойдёт любой способ
ГВ>{
ГВ> MyMakeFunction();
ГВ>}
ГВ>
ГВ>В таком случае линкер не имеет права удалять _dummy и, соответственно, MyMakeFunction со всеми последствиями не будет удалена тоже.
Шаманил я уже по-всякому, и в барабаны бил, и в трубы дудел, не сдается Code Warrior 7 for Windows. Код такой:
/**********************************************
File B.cpp
**********************************************/#include"B.h"// множество перепробованных комбинаций :) extern B* CreateB()
{
return new B();
}
extern A a("class B", (creator_t) CreateB);
/*extern "C" B* CreateB()
{
return new B();
}
extern "C" A a("class B", (creator_t) CreateB);
*/
/*B* B::CreateB()
{
return new B();
}
A B::a("class B", (creator_t) B::CreateB);
*/
B::B()
{
cerr<<"B created"<<endl;
}
/**********************************************
File main.cpp
**********************************************/#include"A.h"//#include "B.h" int main(void)
{
const char* str = "class B";
//B b;
A::GetInstanceByName(str);// не проходит B::B() пока не разкоментирую предидущую строку, тогда два раза конструктор вызывается и конструктор класса А тоже проходитreturn 0;
}
И все это безобразие происходит когда классы А и В во внешней либ находятся и к маин ехе прилинковываются, а когда собираю все классы в рамках одного ехе тогда все нормально, тогда и статик поля классов нормально работают...
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.