Здравствуйте, roma_k, Вы писали:
_>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!! _>// Заголовок
class nvString
{
public:
// constructor
nvString();
// Construct a string from a char pointer
nvString(const char* inStr);
// Copy-constructor
nvString(const nvString& inStr);
// destructorvirtual ~nvString();
// Type cast to char pointerinline operator const char *() const
{ return m_buffer; }
// Indexing operatorinline char operator[](int i) const
{ return m_buffer[i]; }
// Сделай еще что-нибудь типа "GetAt()" с проверкой индекса
// Char pointer atribuition operator
const nvString& operator=(const char* inStr);
// Atribuition operatorconst nvString& operator=(const nvString& inStr);
// Такие два оператора, имхо, лучше делать глобальными
// Concatenation operator with a char pointer
nvString operator+(const char* inStr);
// Concatenation operator
nvString operator+(const nvString& inStr);
// Self-concatenation operator with a char pointerconst nvString&operator+=(const char* inStr);
// Self-concatenation operatorconst nvString&operator+=(const nvString& inStr);
void Clear(void);
// Find a sub-string in the stringinline int Find(const char *str) const
{
char *pos=strstr(m_buffer,str);
if (pos == 0)
return -1;
return (int)(pos-m_buffer);
}
// Find the first occurrence of a character in the stringinline int Find(char c) const
{
char *pos = strchr(m_buffer,c);
if (pos == 0)
return -1;
return (int)(pos-m_buffer);
}
// Find the last occurrence of a character in the stringinline int FindLast(char c) const
{
char *pos = strrchr(m_buffer,c);
if (pos == 0)
return -1;
return (int)(pos-m_buffer);
}
// Change the 'i'-th character of the string// Удобнее было бы еще и через индексирование сделать. Через прокси-класс :)inline void SetChar(int i,char c)
{
if (i < (int)strlen(m_buffer))
m_buffer[i] = c;
}
// Crop the first 'n' characters of the stringinline void CropBegin(int n)
{
if (n < (int)strlen(m_buffer))
{
strcpy(m_buffer,&m_buffer[n]);
}
}
// А сравнения с nvString?
// equal compare operator
inline int operator==(const char *str) const
{ return strcmp(m_buffer,str)==0; }
inline int operator!=(const char *str) const
{ return strcmp(m_buffer,str)!=0; }
inline int operator>(const char *str) const
{ return strcmp(m_buffer,str)>0; }
inline int operator<(const char *str) const
{ return strcmp(m_buffer,str)<0; }
inline int operator>=(const char *str) const
{ return strcmp(m_buffer,str)>=0; }
inline int operator<=(const char *str) const
{ return strcmp(m_buffer,str)<=0; }
// Compare with a char pointerinline int Compare(const char *str) const
{ return strcmp(m_buffer,str); }
// Compare the first 'n' characters of the string with a char pointerinline int Compare(const char *str,int n) const
{ return strncmp(m_buffer,str,n); }
// Compare with a char pointer, case-insensitive flavourinline int CompareNoCase(const char *str) const
{ return stricmp(m_buffer,str); }
// Change all characters to lower-caseinline void ToLower()
{ strlwr(m_buffer); }
// Change all characters to upper-caseinline void ToUpper()
{ strupr(m_buffer); }
// Return the length of the string in bytes// Это кэшировать надоinline int Length() const
{ return m_nLength; }
private:
char *m_buffer;
int m_nLength;
};
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, roma_k, Вы писали:
_>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!!
1. чем этот String лучше других?
2. почему С текст не форматирован?
3. вместо int надо size_t (где речь идет о длинах)
4. почему StrDuplicate не в классе?
5. где поддержка UNICODE?
6. в += используется strcpy/strcat вместо memcpy*2
и вообще там получается ТРИ раза new, и пять копирований строк!!! не многовато ли?
Здравствуйте, roma_k, Вы писали:
_>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!!
Сходу найдено следующее. Если поискать чуть тщательней, то несомневаюсь что список можно расширить в два-три раза.
1) Лишние опреаторы (с учётом того что конструктор не-explicit).
2) Постоянное использование в качестве индекса типа int.
3) До глубины души умиляет SafeArrayDelete (явно внутри что-то типа: if (p) {delete p;})
4) exception-safety и не пахнет (new то может швынуть bad_alloc — не стоит забывать про это)
5) Класс позволяет писать следующие загадочные вещи:
1) почему деструктор виртуальный? у тебя нет ни одного виртуального метода.
2) лучше хранить длину строки в отдельной переменной, а не вызывать каждый раз strlen(). Очень неэффективно получается..
3) оператор индексирования сделан так, что с помощью него не изменить содержимого строки. То есть написать что-то типа такого не получится:
my_str[0] = 'a';
ИМХО, не очень удобно. Я бы предложил такую реализацию:
4) предлагаю функцию StrDuplicate() сделать статической и private класса.
5) не нашел определения функции SafeArrayDelete()...
6) оператор+= реализован очень уж неэффективно.. каждый раз вызывается функция StrDuplicate() [и не раз вызывается], а он выделяет память через new... в общем, задумайся над этим куском кода
7) еще я бы добавил конструктор, который принимает 2 параметра: символ и длину строки. Чтобы вся строка состояла из этих символов.
8) operator+= должен возвращать ссылку на объект твоего класса(а не void!). У тебя нельзя записать так:
my_str2 = my_str1 += "aaaaa";
9) добавь operator+=(const char).
10) добавь operator+(const char).
11) добавь operator=(const char).
12) может память выделять немного заранее? то есть сначала выделяем какой-то кусок памяти, его используем. Если не хватает памяти для какой-то операции, выделяем новый кусок памяти(например, в 2 раза больше, чем старый), копируем туда содержимое и освобождаем память под старый буффер. хоть и памяти будет жрать больше, работать будет быстрее. так реализовано(по аналогии) в std::string.
3) удачи
Здравствуйте, LIS, Вы писали:
LIS>Здравствуйте, _AK_, Вы писали:
_AK>>3) До глубины души умиляет SafeArrayDelete (явно внутри что-то типа: if (p) {delete p;})
LIS>А можно спросить — чем плохо использование такой конструкции?
Это не плохо, просто смысла в проверке никакого.
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, LIS, Вы писали:
LIS>>Здравствуйте, _AK_, Вы писали:
_AK>>>3) До глубины души умиляет SafeArrayDelete (явно внутри что-то типа: if (p) {delete p;})
LIS>>А можно спросить — чем плохо использование такой конструкции? __>Это не плохо, просто смысла в проверке никакого.
А как же проверить что объект был удален до этого?
Я вот делаю так:
#define DELETE_P if (p) { delete p; p = NULL; }
и потом когда еще раз пытаюсь удалить объект, то никаких exception не валится (хотя обработку все равно надо ставить).
Здравствуйте, LIS, Вы писали:
LIS>Здравствуйте, _nn_, Вы писали:
__>>Здравствуйте, LIS, Вы писали:
LIS>>>Здравствуйте, _AK_, Вы писали:
_AK>>>>3) До глубины души умиляет SafeArrayDelete (явно внутри что-то типа: if (p) {delete p;})
LIS>>>А можно спросить — чем плохо использование такой конструкции? __>>Это не плохо, просто смысла в проверке никакого.
LIS>А как же проверить что объект был удален до этого? LIS>Я вот делаю так:
LIS>
LIS>#define DELETE_P if (p) { delete p; p = NULL; }
LIS>
Можно писать и так :
delete p;
p=NULL;
LIS>и потом когда еще раз пытаюсь удалить объект, то никаких exception не валится (хотя обработку все равно надо ставить).
рекомендует избавиться от operator const char *. Он разбирает похожий пример, но для указателей.
Еще я не могу оценить смысл виртуальности деструктора.
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, roma_k, Вы писали:
_>>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!! _>>// Заголовок Н>
Н>class nvString
Н>{
Н>public:
Н> // Return the length of the string in bytes
Н> // Это кэшировать надо
Н> inline int Length() const
Н> { return m_nLength; }
Н>private:
Н> int m_nLength; // Может mutable ?
Н>};
Н>
Здравствуйте, SergeMukhin, Вы писали:
SM>Здравствуйте, roma_k, Вы писали:
_>>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!!
SM>3. вместо int надо size_t (где речь идет о длинах)
Почему ?
SM>5. где поддержка UNICODE?
Должна быть?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Здравствуйте, AndrewJD, Вы писали:
AJD>Здравствуйте, SergeMukhin, Вы писали:
SM>>Здравствуйте, roma_k, Вы писали:
_>>>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!!
SM>>3. вместо int надо size_t (где речь идет о длинах) AJD>Почему ?
например strlen выдает size_t, и так для переносимости.
SM>>5. где поддержка UNICODE? AJD>Должна быть?
Здравствуйте, Вадим Никулин, Вы писали:
ВН>Здравствуйте, Нахлобуч, Вы писали:
Н>>Здравствуйте, roma_k, Вы писали:
_>>>Оцените пожалуйста, интересны все мои ошибки, особенно в реализации операторов !!! _>>>// Заголовок Н>>
Н>>class nvString
Н>>{
Н>>public:
Н>> // Return the length of the string in bytes
Н>> // Это кэшировать надо
Н>> inline int Length() const
Н>> { return m_nLength; }
Н>>private:
Н>> int m_nLength; // Может mutable ?
Н>>};
Н>>
А смысл? Там же нет константных функций, которые чего-то с длиной делают.
HgLab: Mercurial Server and Repository Management for Windows
_>При таком варианте приходится полагатся, на разработчиков компиляторов,а также на разработчиков библиотек.
ну вы даете!
1. причем тут компилятор?
2. неужели могут быть сомнения, что при реализации delete разработчики допустят такую ошибку?
_>Так надежней. Хотя и устарело...