lamerok 0 14 мая, 2007 Опубликовано 14 мая, 2007 · Жалоба Посмотрите плз картинку. Почему ИАР ругается на инициализацию статического члена класса, при этом на инициализацию не статического члена говорит, что атрибут должен быть статическим????. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 14 мая, 2007 Опубликовано 14 мая, 2007 · Жалоба Посмотрите плз картинку. Почему ИАР ругается на инициализацию статического члена класса, при этом на инициализацию не статического члена говорит, что атрибут должен быть статическим????.Попробуйте так:class cClassDir { private: static tF32 const initVolt; tF32 const initTest; }; // in .cpp: cClassDir::cClassDir() : initTest(4.0f) {} tF32 cClassDir::initVolt = 5.0f; P.S. А виноват, конечно, компилятор :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 14 мая, 2007 Опубликовано 14 мая, 2007 · Жалоба Статические члены класса определяются и инициализируются отдельно, т. к. под них выделяется память и единожды, т. к. определение класса может быть помещено в хёдер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба Попробуйте так:class cClassDir { private: static tF32 const initVolt; tF32 const initTest; }; // in .cpp: cClassDir::cClassDir() : initTest(4.0f) {} tF32 cClassDir::initVolt = 5.0f; P.S. А виноват, конечно, компилятор :) Спасибо, так компилятор съел... const float cClass::initialVoltValueRange = 800.0f; const float cClass::initialCurValueRange = 0.5f; const float cClass::initialTestValue = 8.0f; cClass::cClass(void) { internalVoltRange = initialVoltValueRange; internalCurRange = initialCurValueRange; internalTest = initialTestValue; } но вот что получилось в ассемблере.... 66 internalVotlRange = initialVoltValueRange; \ 000000C4 .... LDI R16, LOW(??initialVoltValueRange) \ 000000C6 .... LDI R17, (??initialVoltValueRange) >> 8 \ 000000C8 01F8 MOVW R31:R30, R17:R16 \ 000000CA 8140 LD R20, Z \ 000000CC 8151 LDD R21, Z+1 \ 000000CE 8162 LDD R22, Z+2 \ 000000D0 8173 LDD R23, Z+3 \ 000000D2 01F3 MOVW R31:R30, R7:R6 \ 000000D4 AF41 STD Z+57, R20 \ 000000D6 AF52 STD Z+58, R21 \ 000000D8 AF63 STD Z+59, R22 \ 000000DA AF74 STD Z+60, R23 67 internalCurRange = initialCurValueRange; \ 000000DC 01F8 MOVW R31:R30, R17:R16 \ 000000DE 8144 LDD R20, Z+4 \ 000000E0 8155 LDD R21, Z+5 \ 000000E2 8166 LDD R22, Z+6 \ 000000E4 8177 LDD R23, Z+7 \ 000000E6 934D ST X+, R20 \ 000000E8 935D ST X+, R21 \ 000000EA 936D ST X+, R22 \ 000000EC 937C ST X, R23 \ 000000EE 9713 SBIW R27:R26, 3 68 internalTest = initialTestValue; \ 000000F0 8500 LDD R16, Z+8 \ 000000F2 8511 LDD R17, Z+9 \ 000000F4 8522 LDD R18, Z+10 \ 000000F6 8533 LDD R19, Z+11 \ 000000F8 01FD MOVW R31:R30, R27:R26 \ 000000FA 8304 STD Z+4, R16 \ 000000FC 8315 STD Z+5, R17 \ 000000FE 8326 STD Z+6, R18 \ 00000100 8337 STD Z+7, R19 Т.е. данные берутся из ОЗУ а нужно из памяти программ.... Опять глюк компилятора???? Кстати из первого моего поста, если не делать атрибут класса статическим и проинициализировать его, то ИАР дает предупреждение, как видно на картинке (говорит, что не стаический член класса не рекумендуется инициализировать, сделайте его статическим). И выдает верный код в ассемблере!!!!! Т.е подставляет непосредственно число (LDI R16, 0 -> LDI R18, 72 -> LDI R19, 68). См. код 66 internalVoltRange = initialVoltValueRange; \ 000000C0 E000 LDI R16, 0 \ 000000C2 E428 LDI R18, 72 \ 000000C4 E434 LDI R19, 68 \ 000000C6 01F2 MOVW R31:R30, R5:R4 \ 000000C8 AF01 STD Z+57, R16 \ 000000CA AF02 STD Z+58, R16 \ 000000CC AF23 STD Z+59, R18 \ 000000CE AF34 STD Z+60, R19 67 internalCurRange = initialCurValueRange; \ 000000D0 EC0D LDI R16, 205 \ 000000D2 EC1C LDI R17, 204 \ 000000D4 E33E LDI R19, 62 \ 000000D6 01F3 MOVW R31:R30, R7:R6 \ 000000D8 8300 ST Z, R16 \ 000000DA 8311 STD Z+1, R17 \ 000000DC 8312 STD Z+2, R17 \ 000000DE 8333 STD Z+3, R19 68 internalTest = initialTestValue; \ 000000E0 E000 LDI R16, 0 \ 000000E2 E010 LDI R17, 0 \ 000000E4 8304 STD Z+4, R16 \ 000000E6 8305 STD Z+5, R16 \ 000000E8 8306 STD Z+6, R16 \ 000000EA 8307 STD Z+7, R16 Ничего не понимаю.... Обращаться в ИАР???? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 50 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба Т.е. данные берутся из ОЗУ а нужно из памяти программ.... Опять глюк компилятора???? А с чего он должен во флеши-то появиться? От того, что объявили const? Нет, это не причина - сегмент const на платформе AVR расположен в области ОЗУ и никак он во флешь попасть не может. Именно по этой причине и введено расшинение для AVR в виде ключевого слова __flash. Кстати из первого моего поста, если не делать атрибут класса статическим и проинициализировать его, то ИАР дает предупреждение, Совершенно правильно - нестатические члены-данные класса надо иницилизировать в конструкторе - для этого он и предназначен. как видно на картинке (говорит, что не стаический член класса не рекумендуется инициализировать, сделайте его статическим). И выдает верный код в ассемблере!!!!! Делать те или иниые члены статическими или нестатическими надо не по советам компилятора, а на основе собственного замысла - автор программы-то Вы, Вам и решать, что и как лучше реализовать. А классы, их члены, нестатические и статические - это лишь средства (как и все остальное). Небольшой хинт: статические члены класса - это по сути обычные глобальные переменные, только помещенные в область видимости класса и если это функции (статические функции-члены), то имеющие доступ к закрытым членам класса. Только и всего. Именно поэтому статические члены-данные надо создавать (выделять под них память) и инициализировать как обычные глобальные переменные (только надо квалифицировать именем класса, т.к. они находятся в его scope (области видимости)). Остальные правила точно такие же, как и с обычными глобальными переменными. Жить такой статический член-данное может совей жизнью - может быть не создано ни одного объекта класса, а этот существует сам по себе. Инициализируется он так же на этапе статической иницализации (когда инициализируются все глобальные объекты не класс типов), которая по Стандарту осуществляется до динамической инициализации (вызова конструкторов объектов), и это обстоятельство может быть использовано - во время вызова конструктора статический член-данное уже гарантировано проициализирован. Ничего не понимаю.... Обращаться в ИАР???? IAR тут совершенно не причем, надо просто подучить С++. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба А с чего он должен во флеши-то появиться? От того, что объявили const? Нет, это не причина - сегмент const на платформе AVR расположен в области ОЗУ и никак он во флешь попасть не может. Именно по этой причине и введено расшинение для AVR в виде ключевого слова __flash. 1. Я не говориил, что static const Должен быть во Флеше. Я говорил, что правильный компилятор, Должен static const параметр в коде просто подменить числом!!!! Число естественно лежит в коде (во флеше) :) См последний дизамблер с прошлого поста. Он так и сделал, но при этом я не писал, что атрибут static!!!! а просто написал const tF32 internalVoltValueRange = 800.0f Совершенно правильно - нестатические члены-данные класса надо иницилизировать в конструкторе - для этого он и предназначен. Делать те или иниые члены статическими или нестатическими надо не по советам компилятора, а на основе собственного замысла - автор программы-то Вы, Вам и решать, что и как лучше реализовать. А классы, их члены, нестатические и статические - это лишь средства (как и все остальное). Вот нестатический мне не нужен. Но компилятор не воспринимает почему-то статический тип и не хочет его инициировать. Замысел. Объявляем static const атрибут в классе, инициализируем его и это у нас получается, если по Сишному сказать как бы #define. Т.е компилятор в коде должен подставлять не саму пременную, а только число. Так и просиходит, но только в случае если я static нее ставлю перед const. Вопрос почему???? internalVoltRange = initialVoltValueRange; \ 000000C0 E000 LDI R16, 0 //00h 00h 73h 68h = 800.0f \ 000000C2 E428 LDI R18, 72 \ 000000C4 E434 LDI R19, 68 // Class.h class cClass { public: float getInternalVoltRange(void) const { return internalVoltRange; } float getInternalCurRange(void) const { return internalCurRange; } float getInternalTest(void) const { return internalTest; } private: float internalVoltRange; float internalCurRange; float internalTest; const float initialVoltValueRange = 800.0f; // Что за вата??? Почему так можно вообще делать??? // static const float initialVoltValueRange = 800.0f; // А вот так почему нельзя???? const float initialCurValueRange = 0.40f; // static const float initialCurValueRange = 0.40f; const float initialTestValue = 0.0f; // static const float initialTestValue = 0.0f; }; // Class.cpp ... //const float cClass::initialVoltValueRange = 800.0f; //const float cClass::initialCurValueRange = 0.5f; //const float cClass::initialTestValue = 8.0f; cClass::cClass(void) { internalVoltRange = initialVoltValueRange; internalCurRange = initialCurValueRange; internalTest = initialTestValue; } Именно поэтому статические члены-данные надо создавать (выделять под них память) и инициализировать как обычные глобальные переменные Но только не static const. Как таковой переменной не существует, есть некий идентификатор только, который компилятор подменяте конктретным числом. IAR тут совершенно не причем, надо просто подучить С++. :) ИАР причем, а C++ изучать - так это всем надо сделать :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба Но только не static const. Как таковой переменной не существует, есть некий идентификатор только, который компилятор подменяте конктретным числом.Еще раз, по губам: Объявлен (описан тип) статический член класса в объявлении класса, которое обычно в .h и которое через include может быть включено в несколько .cpp - файлов. Определен этот член и проинициализирован (ему присвоено значение) в каком-то из .cpp файлов. Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену? ИАР причемКто бы сомневался, один lamerok д'Артаньян Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба Еще раз, по губам: Объявлен (описан тип) статический член класса в объявлении класса, которое обычно в .h и которое через include может быть включено в несколько .cpp - файлов. Определен этот член и проинициализирован (ему присвоено значение) в каком-то из .cpp файлов. Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену? Это не обязательно знать компилятору. А линкер, при сборке проекта, будет это знать в любом случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба Это не обязательно знать компилятору. А линкер, при сборке проекта, будет это знать в любом случае. Вот линкер и знает, и настраивает адрес константы в сегменте данных. А у lamerok претензии, что константа не прямо в коде (кодовом серменте) находится. А это компилятор мог-бы сделать, и ему даже сказали, что это константа, но ее значение ему в общем случае неведомо по указанной Сергеем причине. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену? Логично, если компилер должен в одном *.cpp файле подставить значение которе определено в том *.сpp, а в другом *.cpp которое в том *.cpp. Так как компилер компилт последовательно все *.cpp файлы. Кто бы сомневался, один lamerok д'Артаньян Если ИАР не причем,тогда встречный вопрос. ИАР вот такую конструкцию (опять повторюсь): // Class.h class cClass { public: float getInternalVoltRange(void) const { return internalVoltRange; } float getInternalCurRange(void) const { return internalCurRange; } float getInternalTest(void) const { return internalTest; } private: float internalVoltRange; float internalCurRange; float internalTest; const float initialVoltValueRange = 800.0f; // Что за вата??? Почему так можно вообще делать??? const float initialCurValueRange = 0.40f; const float initialTestValue = 0.0f; }; // Class.cpp ... //const float cClassDirector::initialVoltValueRange = 800.0f; //const float cClassDirector::initialCurValueRange = 0.5f; //const float cClassDirector::initialTestValue = 8.0f; cClass::cClass(void) { internalVoltRange = initialVoltValueRange; internalCurRange = initialCurValueRange; internalTest = initialTestValue; } воспринимает как я и задумал, но только почемуто без static И делает подставку числа: internalVoltRange = initialVoltValueRange; \ 000000C0 E000 LDI R16, 0 //00h 00h 73h 68h = 800.0f \ 000000C2 E428 LDI R18, 72 \ 000000C4 E434 LDI R19, 68 Класс у меня синглтон. Но что будет делать ИАР, если я сделаю класс не синглтон, а создам потом два экземпляра этого класса. ЧТО будет подставлять ИАР вместо атрибута const tF32 initialVoltValueRange?????? ОН не статик и по сути они различаться у разных объектов. На сколько я понимаю, ИАР как раз в этом случае должен создавать атрибуты у каждого объекта, которые будут занимать память, т.е. что я получил когда сделал их static ...... . Таким образом ИАР делает все наоборот. (Кстати инициализировать, не статические атрибуты можно только в консрукторе, но только не для ИАР!!!) А если они конст (но не статик), то ИАР должен следить за тем, чтобы я их не поменял потом, но уж точно не делать подмену на число. Кстати к вопросу о ИАР багах... Синглетон у меня сделан макросом только из-за того, что вот такая конструкция компилируется в ИАР 4.21А, но убивает симулятор. А в 4.12А убивает компилятор. //singleton.h #include <new> template <class T> class cSingleton { public: _Pragma("inline=forced") inline static T* getInstance(void) { return pInstance; } protected: static void create(void) { pInstance = new(nothrow) cSingleton(); } cSingleton(void); private: cSingleton(const T& other); const T& operator=(const T& other); static T* pInstance; }; //singleclass.h #include "singleton.h" class cSingleClass : public cSingleton<cSingleClass> { public: static void runTest() {}; private: tF32 test; }; //main.cpp #include "singleclass.h" int main() { cSingleClass::runTest(); return 0; } Если убрать new, то все хорошо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Кажется, компилер должен в одном *.cpp файле подставить значение которе определено в том *.сpp, а в другом *.cpp которое в том *.cpp. Так как компилер компилт последовательно все *.cpp файлы.Не должен!!! Потому что значение статического члена должно быть определено только в одном cpp-файле. Не путайте константную переменную и константный член. Это константная переменная может в разных файлалх иметь одинаковое имя и разное значение. ЧТО будет подставлять ИАР вместо атрибута const tF32 initialVoltValueRange?????? ОН не статик и по сути они различаться у разных объектов.Раз он отличается у разных объектов, значит это обычный константный член. Раз это обычный член, вы его можете проинициализировать в конструкторе. Раз обычный член - константный, значит конструктор - это единственное место, где вы можете его проинициализировать. воспринимает как я и задумал, но только почемуто без static И делает подставку числа: Это очень частный случай и работа оптимизатора - инициализация оказалась в этом же .cpp - файле и компилятор использовал этот факт (однажды такое поведение сыграло со мной злую шутку - константой был серийный номер, который перед прошивкой проставлялся непосредственно в hex. Как же было весело, когда функции из одного .cpp файла откликались на правильный номер, а из другого - на неправильный). Про остальное чуть позже допишу, если никто не опередит. P.S. Машина - дура (ИАР тоже), это не подвергается сомнению. Но не потому, что не делает то, что вы хотите, а наоборот, потому что вместо этого тупо делает именно то, что вы ему написали. Если то, что вы хотите и то, что вы написали - разные вещи, то при чем здесь ИАР? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Не должен!!! Потому что значение статического члена должно быть определено только в одном cpp-файле. Не путайте константную переменную и константный член. Это константная переменная может в разных файлалх иметь одинаковое имя и разное значение. Почему в одном месте???? Стандарт не воспрещает этого... Проверил на других компиляторах, везде один и тот же результат, подстановка конктретного числа. Например, на 4.12А лицензионном прокатило... Может быть опции у компилятора, какие нибудь нужно поставить???? ЧТобы он воспринимал это как надо??? Раз он отличается у разных объектов, значит это обычный константный член. Раз это обычный член, вы его можете проинициализировать в конструкторе. Раз обычный член - константный, значит конструктор - это единственное место, где вы можете его проинициализировать. Полностью согласен, тогда чего же ИАР мне позволил инициализацию (не статика) сделать не в конструкторе??? И заменл все это числом???? P.S. Машина - дура (ИАР тоже), это не подвергается сомнению. Но не потому, что не делает то, что вы хотите, а наоборот, потому что вместо этого тупо делает именно то, что вы ему написали. Если то, что вы хотите и то, что вы написали - разные вещи, то при чем здесь ИАР? Когда я инициализирую константу в хидере класса... не савля статик (Такого делать вообще нельзя) ИАР делает то чтоя задумал сделать со статиком..... ТОгда какого хрена он не делает тоже самое со статиком???? Самое интересное другое... Все это не работает только с флоатом... с интом16, инт8, инт 32 все прекрасно канает на всех компиляторах. И кстати в любом случае результат действия: internalVoltRange = initialVoltValueRange; в internalVoltRange должнен стать 800.0f верно??? А в случае когда статик инициализируется в *.cpp такого не происхит... так как Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Почему в одном месте???? Стандарт не воспрещает этого...Чтобы не толочь дальше воду в ступе, приведите выдержку из стандарта. Когда я инициализирую константу в хидере... не савля статик (Такого делать вообще нельзя)Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету: C++ изучать - так это всем надо сделатьРазберитесь, наконец, чем статический константный член отличается от статической константной переменной. Для константной переменной найдите в книжке, чем отличаются записи int const A = 2; и extern int const A = 2;, тогда вы поймете почему первую запись можно вставлять в .h а второую только в .cpp Для константного члена помедитируйте над ключевым словом mutable. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Вот что получается... в мар файле Мои переменные лежат в коде сегменте NEAR_C Relative segment, address: CODE 00000406 - 00000411 (0xc bytes), align: 0 Segment part 9. Intra module refs: cClassDirector::cClassDirector() ENTRY ADDRESS REF BY ===== ======= ====== cClassDirector::initialVoltValueRange 0000040A cClassDirector::initialCurValueRange 0000040E cClassDirector::initialTestValue 00000406 а в ассемблере берутся из ОЗУ.... internalVolt = initialUSLValue; \ 000000D8 .... LDI R30, LOW(??initialVoltValueRange) \ 000000DA .... LDI R31, (??initialVoltValueRange) >> 8 \ 000000DC 8100 LD R16, Z \ 000000DE 8111 LDD R17, Z+1 \ 000000E0 8122 LDD R18, Z+2 \ 000000E2 8133 LDD R19, Z+3 \ 000000E4 01FC MOVW R31:R30, R25:R24 \ 000000E6 5AE6 SUBI R30, 166 \ 000000E8 4FFF SBCI R31, 255 \ 000000EA 8300 ST Z, R16 \ 000000EC 8311 STD Z+1, R17 \ 000000EE 8322 STD Z+2, R18 \ 000000F0 8333 STD Z+3, R19 И что это ИАР сделал, то что я ему написал:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lamerok 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Чтобы не толочь дальше воду в ступе, приведите выдержку из стандарта. Явно в стандарте не указано что так делать нельзя... нельзя значит можно... Такое в С++ делать можно. Раз вы этого не знаете - последуйте своему совету: См картинку раздел 4........ Внимание, вопрос: откуда компилятор, компилируя другой .cpp - файл знает, какое значение вы присвоили этому члену? Ну опять в разных файлах можно завадать разные значения const float cClass::initialTestValue = 8.0f; в одном скажем и const float cClass::initialTestValue = 10.0f; в другом, если они объявлены статиком И... Так как мы в каждом *.cpp файле подключаем один и тот же хидер, то компилятор должен увидеть что initialTestValue это статический член, да еще и константа, и никакой не external - память под него выделяТь не надо!!!!!!. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться