Я пытаюсь записать свой собственный Строковый класс 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++, и таким образом я не думаю, что это должно иметь так большую часть значения
Строка:
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" будет уничтожена (вызовом деструктора) после построения.
В принципе, похоже, что ваш код работает более или менее так, как ожидалось.
Не используйте strlen, сохраните собственную длину строки. Строка не должна зависеть от того, имеет ли она нулевой терминатор. Можно использовать такие, если вы переданы в случайном const char*, но для внутренних операций,вы должны использовать размер.
Кроме того, вы забыли сделать перегрузку оператора const char*.
Несколько допущенных вами ошибок:
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;
}
Вот что происходит:
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 ничего не выводится.