Класс пользовательской строки (C++)

Я пытаюсь записать свой собственный Строковый класс C++ в целях потребности и образовательном.
Первая вещь состоит в том, что я не знаю так много об операторах, и вот почему я хочу изучить их. Я начал писать свой класс, но когда я выполняю его, он блокирует программу, но не делает никакого катастрофического отказа.
Смотрите на следующий код прежде, чем читать далее:

class CString
{
private:
  char* cstr;
public:
  CString();
  CString(char* str);
  CString(CString& str);
  ~CString();

  operator char*();
  operator const char*();
  CString operator+(const CString& q)const;
     CString operator=(const CString& q);
};

В первую очередь, я не так уверен, что объявил все правильное. Я попробовал googleing об этом, но все учебные руководства о перегрузке объясняют основной ideea, который очень прост, но отсутствие для объяснения, как и когда каждую вещь называют. Например, в моем = оператор программа называет CString (ул. CString&); но у меня нет ideea почему.
Я также присоединил cpp файл ниже:

CString::CString()
{
 cstr=0;
}
CString::CString(char *str)
{
 cstr=new char[strlen(str)];
 strcpy(cstr,str);
}
CString::CString(CString& q)
{
 if(this==&q)
  return;
 cstr = new char[strlen(q.cstr)+1];
 strcpy(cstr,q.cstr);
}
CString::~CString()
{
 if(cstr)
  delete[] cstr;
}
CString::operator char*()
{
 return cstr;
}
CString::operator const char* ()
{
 return cstr;
}
CString CString::operator +(const CString &q) const
{
 CString s;
 s.cstr = new char[strlen(cstr)+strlen(q.cstr)+1];
 strcpy(s.cstr,cstr);
 strcat(s.cstr,q.cstr);
 return s;
}
CString CString::operator =(const CString &q)
{
 if(this!=&q)
 {
  if(cstr)
   delete[] cstr;
  cstr = new char[strlen(q.cstr)+1];
  strcpy(cstr,q.cstr);
 }
 return *this;
}

Для тестирования я использовал код, настолько простой
CString = CString ("привет") + CString (" мир");
printf (a);
Я пытался отладить его, но в точке я заблудился. Сначала это вызывает конструктора 2 раза для "привет" и для "мира". Затем это get's в + оператор, который прекрасен. Затем это вызывает конструктора для пустой строки. После этого это get's в "CString (ул. CString&)" и теперь я потерян. Почему это происходит? После этого я заметил свою строку, содержащую "Привет, Мир" находится в деструкторе (несколько раз подряд). Снова я очень puzzeled. После преобразования снова из символа* к Cstring и назад и вперед это останавливается. Это никогда get's в = оператор, но, и при этом это не идет далее. printf (a) никогда не достигается.
Я использую VisualStudio 2010 для этого, но это - в основном просто стандартный код C++, и таким образом я не думаю, что это должно иметь так большую часть значения

6
задан Sanctus2099 16 May 2010 в 10:54
поделиться

4 ответа

Строка:

cstr=new char[strlen(str)];

должна быть:

cstr=new char[strlen(str) + 1];

Также, проверка на самоприсвоение не имеет смысла в конструкторе копирования - вы создаете новый объект - он не может иметь тот же адрес, что и любой существующий объект. А конструктор копирования должен принимать в качестве параметра ссылку const,

Если в вашем коде вы ожидали, что будет использоваться оператор присваивания, то вы ожидали неправильно. Этот код:

CString a = CString("Hello") + CString(" World");

по сути является тем же самым, что и:

CString a( CString("Hello") + CString(" World") );

который является конструктором копирования, а не присвоения. Временная строка CString "Hello world" будет уничтожена (вызовом деструктора) после построения.

В принципе, похоже, что ваш код работает более или менее так, как ожидалось.

4
ответ дан 16 December 2019 в 21:36
поделиться

Не используйте strlen, сохраните собственную длину строки. Строка не должна зависеть от того, имеет ли она нулевой терминатор. Можно использовать такие, если вы переданы в случайном const char*, но для внутренних операций,вы должны использовать размер.

Кроме того, вы забыли сделать перегрузку оператора const char*.

3
ответ дан 16 December 2019 в 21:36
поделиться

Несколько допущенных вами ошибок:

1. Подпись конструктора копирования неверна. Это должно быть:

CString(const CString& q)

2. op = подпись неверна. Это должно быть:

CString& operator=(const CString& q)

Кстати, по этой же причине был вызван конструктор копирования. Вы вернули * this в конце, который скопировал объект (с вашей op = подписью).

3. Вы разрешаете экземпляры CString с cstr == NULL (ваш конструктор по умолчанию создаст такой экземпляр). Хотя почти во всех функциях (конструктор копирования, оператор + , оператор = ) вы плохо справляетесь с этим случаем ( q.cstr == NULL ) .

Возможно, самым простым и безопасным способом было бы просто запретить этот случай и изменить конструктор по умолчанию на:

CString::CString()
{
   cstr = new char[1];
   cstr[0] = 0;
}
0
ответ дан 16 December 2019 в 21:36
поделиться

Вот что происходит:

  1. Конструктор действительно вызывается дважды. Один раз для "hello" и один раз для " world". Порядок не определен.
  2. Оператор CString::operator + вызывается на первой CString ("hello"), передавая вторую CString ("world") в качестве аргумента. Возвращаемым значением CString::operator + является новая CString
  3. Поскольку вы присваиваете при инициализации, то есть: CString a = [CString result of operator +], c++ просто вызовет ваш конструктор копирования. Отсюда вызов CString(CString& ), который вы видите в отладчике.

Итак, всего создано 4 объекта, по одному для каждого строкового литерала ("hello" и " world"), один для их конкатенации (результат вызова CString::operator+) и один для хранения результата (CString a = ...). Для каждого из этих временных объектов будет вызван свой деструктор.

Что касается того, почему вы не получаете printf, я понятия не имею. Я просто скопировал ваш код в этот файл:

#include <cstdio>
#include <cstring>

[your code]

int main(int argc,char* argv[]) {
  CString a = CString("hello") + CString(" world");
  printf(a);
}

И когда я запустил получившийся исполняемый файл, я получил hello world в качестве вывода. Это на Ubuntu с g++ 4.4. Не совсем понимаю, почему в отладчике VS ничего не выводится.

1
ответ дан 16 December 2019 в 21:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: