Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Непонятка с CString

350
14 июня 2006 года
cheburator
589 / / 01.06.2006
Проект C++ не managed под MS VS .NET.
Есть две строки CString text и CString result.
При попытке добавить к result некоторый символ из строки text компилятор ругается на что-то типа "есть несколько подходящих реализаций шаблона, какое, Фауст, ты предпочитаешь?":

 
Код:
CString GetLexema (CString text, DWORD &pos)
{
  CString result;
  DWORD len = text.GetLength();
  for (; pos<len; pos++)
    result += text[pos];  // <-- здесь ругается на CSimpleStringT
};

Я так понимаю, проблема из-за того, что строка CString в MS VC .NET реализована как шаблон, что-то типа class CSimpleStringT<typename type, bool m_bMFCATL>, а CString от нее производный. В старых версиях такой проблемы не возникало.
Я вышел из тупика таким способом:
Код:
CString GetLexema (CString text, DWORD &pos)
{
  CString result;
  char symbol;
  DWORD len = text.GetLength();
  for (; pos<len; pos++)
  {
    symbol = ((LPCSTR)text)[pos];
    result += symbol;
  };
};

Можно ли написать по-человечьи, без char symbol, и без оператора (LPCSTR)?
3
14 июня 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=cheburator]
Я так понимаю, проблема из-за того, что строка CString в MS VC .NET реализована как шаблон, что-то типа class CSimpleStringT<typename type, bool m_bMFCATL>, а CString от нее производный. В старых версиях такой проблемы не возникало.
[/QUOTE]
Давай начнем с того, что MSVS.NET - среда разработки, а не библиотека классов. Сл-но класс CString имеет отношение к конкретной библиотеке (MFC, ATL/WTL), а не среде разработки.
Раньше MFC и ATL/WTL имели каждый свой класс CString, поэтому твоей проблемы раньше и не возникало.
С недавнего времени библиотека MFC заимствовала класс CString (как и некоторые другие, см. MSDN "Classes Shared Between MFC and ATL") из библиотеки ATL/WTL.

[QUOTE=cheburator]
Я вышел из тупика таким способом:
Код:
CString GetLexema (CString text, DWORD &pos)
{
  CString result;
  char symbol;
  DWORD len = text.GetLength();
  for (; pos<len; pos++)
  {
    symbol = ((LPCSTR)text)[pos];
    result += symbol;
  };
};

Можно ли написать по-человечьи, без char symbol, и без оператора (LPCSTR)?[/QUOTE]
Проблема не в (LPCSTR), а в том, что у шаблонного класса CSimpleStringT не определен оператор operator [](DWORD), а определен operator [](int).
Решения проблемы
1. CString GetLexema (CString text, int &pos)
2. result += text[(int)pos];
Первый способ предпочтительнее.

Теперь ненсколько замечаний по твоему коду.
1. После операторный скобок не нужна точка с запятой (не путай со скобками в описании классов, структур и пр.)
2. Если объявлено, что функция возвращает значение, она должна его возвращать.
3. Объекты лучше передавать по ссылке (константной). Я бы ввел это как правило и бил бы по рукам.
4. А вот pos по ссылке не передавал бы, т.к. имеет место неявное изменение переменной. Честно говоря, вообще, не вижу особого смысла в твоем коде в передаче pos по ссылке.
5. Конкретно для твоего примера можно было бы воспользоваться уже готовым методом CString::Right, а не городить своё.
350
14 июня 2006 года
cheburator
589 / / 01.06.2006
[QUOTE=Green]Проблема не в (LPCSTR), а в том, что у шаблонного класса CSimpleStringT не определен оператор operator [](DWORD), а определен operator [](int).[/QUOTE]
Спасибо, это я и хотел услышать. Кстати, очень оперативный ответ :)
[QUOTE=Green]
Теперь ненсколько замечаний по твоему коду.
1. После операторный скобок не нужна точка с запятой (не путай со скобками в описании классов, структур и пр.)
[/QUOTE]
Я в курсе, просто дурацкая привычка :) Ну и пусть, будет пустой оператор.
[/QUOTE=Green]
2. Если объявлено, что функция возвращает значение, она должна его возвращать.
3. Объекты лучше передавать по ссылке (константной). Я бы ввел это как правило и бил бы по рукам.
4. А вот pos по ссылке не передавал бы, т.к. имеет место неявное изменение переменной. Честно говоря, вообще, не вижу особого смысла в твоем коде в передаче pos по ссылке.
5. Конкретно для твоего примера можно было бы воспользоваться уже готовым методом CString::Right, а не городить своё.[/QUOTE]

На всё это один ответ: я привел лишь сильно упрощенный отрывок функции. И немного ошибся в постинге: text у меня передается по константной ссылке. CString::Right не годится, и pos ДОЛЖЕН передаваться по ссылке (неконстантной) (т. к. функция ДОЛЖНА изменять переданное значение - так задумано).Значение конечно же тоже возвращается.

Спасибо за исчерпывающий ответ, достойный быть образцовым :)
3
14 июня 2006 года
Green
4.8K / / 20.01.2000
Я бы всетаки сделал бы так:
int GetLexema (const CString& text, CString& result, int pos);

Т.о. не будет неявно изменяться pos, но измененное значение будет возвращаться, и, что не маловажно, не будет создаваться временный объект CString.
350
14 июня 2006 года
cheburator
589 / / 01.06.2006
[QUOTE=Green]Я бы всетаки сделал бы так:
int GetLexema (const CString& text, CString& result, int pos);

Т.о. не будет неявно изменяться pos, но измененное значение будет возвращаться, и, что не маловажно, не будет создаваться временный объект CString.[/QUOTE]
Да, передать result по ссылке - хорошая идея, чтобы не создавать каждый раз "жирный" объект CString.
Но смысла возвращать новую позицию вместо изменения ссылки не вижу, т.к. вызывающая функция все равно присвоит это значение переменной, переданной в качестве агрумента pos. Сама концепция лексического анализатора в том, чтобы считать очередную лексему и "сдвинуть" указатель чтения.
Итак, окончательный вариант:
 
Код:
void /*если сильно хочется вернуть новую позицию, то пусть будет int*/ GetLexema (const CString &text, CString &result, DWORD/*или int*/ &pos) throw;
324
15 июня 2006 года
AndreySar
532 / / 01.08.2004
Используй GetAt(pos)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог