Перегрузка оператора присваивания в C++

162
07 марта 2019, 22:10

Нужна помощь умных людей. Нужно: Создать класс СТРОКА, реализующий текстовую строку. То есть хранит цепочку символов переменной длины, позволяет определить её длину, поддерживает операцию конкатенации и сравнения двух строк. Составить примеры использования и набор тестов.(Задание по варианту: Создать класс ВОСЬМЕРИЧНАЯ_СТРОКА.Добавить возможность заполнения значения строки из числа в двоичной системе). Задание было сделано, но преподавателю нужно добавить перегрузку оператора присваивания и как-то сделать проверку. Код программы прилагается. Основной файл - PROGA.cpp, дополнительный файл - String.h. Файл PROGA.cpp:

#include "String.h"
#include <iostream>
#include <conio.h>
#include <cstring>
#include <cstdlib>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
int main()
{
    setlocale(LC_ALL, "Russian");
    cout << "Лабораторная работа №2"<<endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    getOctStr s("20000");
    getOctStr f("25000");
    cout << "Первая строка: ";
    cout << s << endl;
    cout << "Перевод из восьмеричной в двоичную систему счисления: ";
    cout << s-f << endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    cout << "Вторая строка: ";
    cout << f<< endl;
    cout << "Перевод из восьмеричной в двоичную систему счисления: ";
    cout << f - s << endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    cout << "Склеивание двух строк: ";
    s += f;
    cout << s << endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    cout << "Длина первой строки: ";
    cout << s.getLength() << endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    cout << "Длина второй строки: ";
    cout << f.getLength() << endl;
    cout <<"------------------------------------------------------------------------------"<<endl;
    cout << "Строки равны - 1. Строки не равны - 0"<<endl;
    cout << (s == f) << endl;
        cout <<"------------------------------------------------------------------------------"<<endl;
    _getch();
    return 0;
}
String::String()
{
    Str = 0;
    Length = 0;
}
String::String(const char* ptr)
    : Length(strlen(ptr)), Str(new char[Length + 1])
{
    strcpy(Str, ptr);
}
String::String(const String& t)
    : Length(strlen(t.Str)), Str(new char[Length + 1])
{
    strcpy(Str, t.Str);
}
String& String::operator += (const String& t)
{
    int newLength = Length + t.Length;
    char *newStr = new char[newLength + 1];
    strcpy(newStr, Str);
    strcat(newStr, t.Str);
    delete[] Str;
    Str = newStr;
    Length = newLength;
    return *this;
}
bool String::operator == (const String& t) const
{
    return Length == t.Length && strcmp(Str, t.Str) == 0;
}
bool String::operator != (const String& t) const
{
    return !(operator == (t));
}
bool String::is_empty() const
{
    return Str == 0 || Str[0] == '\0';
}
const char* String::getStr() const
{
    return Str;
}
int String::getLength() const
{
    return Length;
}
ostream & String::show(ostream & os) const
{
    return os << "\"" << (Str ? Str : "") << "\"";
}
String::~String()
{
    Length = 0;
    delete[] Str;
    Str = 0;
}
getOctStr::getOctStr() : String()
{ }
getOctStr::getOctStr(const char* ptr) : String(ptr)
{ }
getOctStr::getOctStr(const getOctStr& t) : String(t)
{ }
String getOctStr::operator - (const String& t) 
{
    const int MAX_BUF = 80;
    char buf[MAX_BUF];
    _ltoa(strtoll(Str, 0, 8), buf, 2);
    return String(buf);
}
getOctStr::~getOctStr()
{
}

Файл String.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <vector>
using namespace std;
class String
{
protected:
    int Length;
    char* Str;
public:
    String();
    String(const char* ptr);
    String(const String& t);
    String& operator += (const String& t);
    bool operator == (const String& t) const;
    String& operator = (const String& t);
    if (this ==&t) {
        return *this;
    }
    Length = t.Length;
    return *this;
    bool operator != (const String& t) const;
    bool is_empty() const;
    const char* getStr() const;
    int getLength() const;
    ostream & show(ostream & os) const;
    friend ostream & operator << (ostream & os, const String & s)
    {
        return s.show(os);
    }
    ~String();
};
class getOctStr : public String
{
public:
    getOctStr();
    getOctStr(const char* ptr);
    getOctStr(const getOctStr& t);
    String operator - (const String& t);
    ~getOctStr();
};

Просто вообще не понятно как это сделать, а сделать нужно. Заранее спасибо за помощь всем кто подскажет. P.S. Буду очень благодарен готовому коду, т.к. я пробовал добавил в String.h строку:

String& operator = (String& t);

А в PROGA.cpp строки:

String& String::operator = (String& t)
{
    swap (Length, t.Length);
    swap (Str, t.Str);
    return *this;
} 

На что мне сказали что swap вообще не используется, а по другому - никак не получается и все не работает. Заранее спасибо за ответ!

Answer 1

Когда вы пишите int a = 1, b = 2; a = b; вы ожидаете что после присваивания а изменится значение b? Операция присваивания не должна менять свой аргумент.

Первый подход к решению вашей задачи: при присваивании освободить текущую строку, выделить память под новую строку и скопировать данные:

String& operator=(const String& t)
{ // аргумент не должен изменятся -> const
    delete[] Str;
    Length = t.Length;
    Str = new char[Length];
    strcpy(Str, t.Str);
    return *this;
}

Этот имеет недостатки, такие как: проблема безопасности исключений, необходимость проверки на присваивание самому себе. Лучшим подход будет использовать copy-and-swap идиому:

String& operator=(const String& t)
{
   String temp{t};
   std::swap(*this, temp);
   return *this;
}

Больше об идиоме copy-and-swap

READ ALSO
работа конструктора String(const char*)

работа конструктора String(const char*)

Был такой вопрос: Преобразование char[] в string

134
Как вывести ноль перед числом. С++

Как вывести ноль перед числом. С++

Через std::setfill('0') задаём заполнитель, через std::setw(N) задаём ширину выводимого числаВсё что не занято самим числом будет заполнено символом-заполнителем

196
C++ curl получить utf-8 в кирилице

C++ curl получить utf-8 в кирилице

Есть документ в интернете в UTF-8

171
переопределение метода qcombobox setText

переопределение метода qcombobox setText

Переопределил стандартный view у QComboBox по этому примеру:

143