Передача константы как агрумента
static const CONST_NAME = 1;
В другом модуле подключаю этот h-файл, и в функцию необходимо передать константу
private void Function(int)
....
Function(CONST_NAME);
так как имя константы получаю в процессе работы приложения в виде строки, то получаю вызов
Function("CONST_NAME");
Подскажите плиз, а то что-то туплю:rolleyes: , как получить из AnsiString имя константы?
т.е. к какому типу мне привести AnsiString или как еще мне передать константу, если имя передаваемой константы может быть известно только в контексте работы приложения (и возвращается как AnsiString)
И как тебе это удается? Покажи код.
Сперва заполнить его
const int CONST_NAME2 = 2;
const int CONST_NAME3 = 3;
TStringList *st;
st = new TStringList();
AnsiString Item = Format("CONST_NAME1=%d", ARRAYOFCONST((CONST_NAME1)));
st->Add(Item);
Item = Format("CONST_NAME2=%d", ARRAYOFCONST((CONST_NAME2)));
st->Add(Item);
Item = Format("CONST_NAME3=%d", ARRAYOFCONST((CONST_NAME3)));
st->Add(Item);
st->Sorted = true;
Function(value);
А если вдруг констант будет около 100 или больше?
const int CONST_NAME2 = 2;
const int CONST_NAME3 = 3;
struct CONSTS
{
char name[28];
int value;
};
CONSTS consts[] =
{
"CONST_NAME1", CONST_NAME1,
"CONST_NAME2", CONST_NAME2,
"CONST_NAME3", CONST_NAME3
};
{
char name[28];
int value;
};
[/QUOTE]
Лучше будет использовать
{
AnsiString Name;
int Value;
};
Во-первых, если будет много функций, использующих AnsiString, то многократные приведения char* к AnsiString замедлят программу.
Во-вторых, если имя константы будет короче 27 символов - то будет напрасное использование оставшейся памяти. А если длиннее - то.....
{
AnsiString Name;
int Value;
};
Во-первых, если будет много функций, использующих AnsiString, то многократные приведения char* к AnsiString замедлят программу.
Во-вторых, если имя константы будет короче 27 символов - то будет напрасное использование оставшейся памяти. А если длиннее - то.....[/QUOTE]Разница между программой с char name[], и Ansistring name - один оператор c_str(). Это врятли может замедлить программу. Особенно, что не исключено, что этот оператор выполняется во время компиляции.
Длину строки нужно выбрать таким, чтоб вместил строку с макс. длиной, и чтоб длина структуры была степенью двойки. Незаполненные пару байт - это не статья расхода.
И каким образом инициализируется матрица при AnsiString Name?. Если для этого нужно писать код, тогда этот вариант явно проигрывает по всем трем параметрам. Быстродействие, память и удобство использования. Ведь при типе char[], если появится новая константа напр. CONST23=23, то, чтоб это обработать нужно только поместить соответствующую строку в список инициализации массива consts.
[/quote]
Приведение AnsiString к char* приводится просто. А вот если функция требует AnsiString, а ей суют char* - всё будет медленнее и дороже :(
И вообще, использовать char* нежелательно - просто потому что никто сейчас не знает всех "подводных камней" этого типа данных :(
Точно также, как и в вашем решении. Пишем "имя константы", и компилятор для инициализации поля автоматически вызовет конструктор AnsiString (const char*). Кстати, коды деструктора, оператора "=", и конструкторов (дефолтного и копирования) компилируются автоматически, даже если разработчик класса/структуры их не объявлял.
Тем более, что список констант будет инициализироваться один раз - при запуске программы. Зато затраты на запуск окупятся сторицей во время выполнения программы.
И вообще, использовать char* нежелательно - просто потому что никто сейчас не знает всех "подводных камней" этого типа данных :(
[/QUOTE]Мда, на форуме появился второй Green. Тихий ужас. :) В данном конкретном случае, нет "А вот если функция требует AnsiString,...", так как нет такой ф-ии. Должна быть написанна ОДНА ф-ия бинарного поиска, которая получая имя константы, возвращает его значение.
Программисты напр. Visual Basic не упадут от смеха, когда узнают, что якобы никто из C++ программистов грамотно работать с архи сложным типом char* не умеет? Поэтому им, от греха подальше, советуют вообще не использовать этот тип? :)
Тем более, что список констант будет инициализироваться один раз - при запуске программы. Зато затраты на запуск окупятся сторицей во время выполнения программы.
Я спрашывал, каким образом инициализируется массив? В случае с char[], достаточно
{
"CONST_NAME1", CONST_NAME1,
"CONST_NAME2", CONST_NAME2,
"CONST_NAME3", CONST_NAME3
};
[/quote]
А что мешает использовать одну функцию, которая использует AnsiString? Или обязательно нужно char*
А падать от удивления, при виде "алгоритмов" работы с char* не приходилось? Если бы все программисты на C++ умели грамотно использовать char[], мир бы никогда не узнал, что такое "переполнение буфера" :) .
Если вы зубры кодинга старой закалки, то примите мои поздравления :) . Если вы считаете себя таковыми - флаг в руки и Access Violation навстречу ;)
{
"CONST_NAME1", CONST_NAME1,
"CONST_NAME2", CONST_NAME2,
"CONST_NAME3", CONST_NAME3
};
Но в случае с AnsiString, не нужно писать отдельный код для каждой констаны?
Повторяю - точно также.
Во избежание двусмысленности, можно вручную реализовать алгоритм инициализации объекта
{[INDENT]AnsiString Name;
int Value;
inline TConsts (const char *iName, int iValue): Name (iName), Value (iValue)
{} // Вызов конструктора с параметрами[/INDENT]};
Вот и вся разница. А код конструктора при создании объекта, выполняется даже если программист не писал его текст.
А почему такое странно предложение использовать именно AnsiString вместо char *. зачем вобще исспользовать без необходимости нестандартные типы. Понятно если проект полностью построен с исспользованием борландовских библиотек - это еще оправданно. Но если же пишется универсальный код, никак не привязанный к билдеру? а какой код пишется здесь - ни слова не сказанно.
Понятно, что char * - это C-way =))) Но все же если вам нужем строковый класс, что вполне логично в c++, есть же вполне стандартный std::string.
Ато странный аргумент, если в функциях часто исспользуется AnsiString.
А если std::string, если CString или CAtlString, если QString и т.д. =))
т.е. к какому типу мне привести AnsiString или как еще мне передать константу, если имя передаваемой константы может быть известно только в контексте работы приложения (и возвращается как AnsiString)[/QUOTE]
Как уже говорили,нужен ассоциативный массив.
Если таких констант много и время поиска ассоциации критично, можно использовать уже предлженный std::map и std::hash_map.
Если констант немного, то можно использовать способ, предложенный Мerlin, но с рядом замечаний:
1) массив следует поместить в спец. функцию, возращающую значение константы по её имени, переданному, как строка;
2) сам массив надо объявить статическим и константным;
3) вместо char name[28], следует использовать const char*;
4) необходимо предусмотреть вариант, когда ассоциации не существует
Т. о. код будет примерно следующим:
{
struct Token {
const char* name;
int value;
};
static const Token consts[] = {
{"CONST_NAME1", CONST_NAME1},
{"CONST_NAME2", CONST_NAME2},
{"CONST_NAME3", CONST_NAME3}
};
for(int i=0; i < sizeof(consts)/sizeof(consts[0]); i++) {
if( !strcmp(name, consts.name) )
return consts.value;
}
return -1; // случай когда имя не найдено
}
для упрощения перечисления ассоциаций можно ввести вспомогательный макрос:
static const Token consts[] =
{
TOKEN(CONST_NAME1),
TOKEN(CONST_NAME2),
TOKEN(CONST_NAME3)
};
Правило простое: не допускать такого приведения НИКОГДА.
для упрощения перечисления ассоциаций можно ввести вспомогательный макрос:
[/QUOTE]
Эстетично, дёшево, надёжно и практично :)
[QUOTE=ask]зачем вобще исспользовать без необходимости нестандартные типы. Понятно если проект полностью построен с исспользованием борландовских библиотек - это еще оправданно. Но если же пишется универсальный код, никак не привязанный к билдеру? а какой код пишется здесь - ни слова не сказанно.
[/QUOTE]
А в какой ветке тема создана - тоже не сказано ;).
Если человек пишет на билдере, более чем вероятно, что используется VCL - следовательно, для работы со всеми экранными компонентами "стандартом" является AnsiString.
В конце концов, что может быть странне чем
// Куча функций по обработке строковых массивов,
// которые могут быть заменены методами AnsiString
Memo1->Strings->Add (Text);
Кстати, прошу прощения, но в приведённом в прошлом моём посте есть ошибка кода. Писал "по памяти", компилировал в уме :)
Писать правильно так - работает на все сто.
TMyStruct ("Value1", 1),
TMyStruct ("Value2", 2),
TMyStruct ("Value3", 3)};
Естественно, конструктор TMyStuct (const char *iName, int iValue) должен существовать :)