2012-04-30 2 views
0

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

Код для оператора + в моем файле .cpp:

MyString& MyString::operator +(const MyString& rhs) 
{ 
    delete [] String; 
    String = new char[rhs.Size]; 
    Size = rhs.Size; 
    // needs to be a loop for cascading + 
    // so that String1=String2+String3+String4 will work 
    for(int i = 0; i < rhs.Size+1 ; i++) 
    { 
    // String[i] + rhs.String[i]; ??? 
    } 
    return *this; 
} 

Код для оператора + = в .cpp файле:

MyString& MyString::operator+=(const MyString& rhs) 
{ 
    delete [] String; 
    String = new char[rhs.Size]; 
    String = String + rhs.String; 
    return *this; 
} 

Зов main.cpp:

String1 = String2 + String3 + String4; 
String1.Print(); 

String2 += String3; 
String2.Print(); 

Я знаю, что мои .cpp-коды файлов неправильные, некоторые прозрения были бы замечательными!

+2

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

+0

Что вам на самом деле нужно + и + = делать, добавить строку? –

+0

Мне нужен оператор +, чтобы объединить две строки (где String1 = String2 + String3 + String4 работает), и мне нужно + =, чтобы иметь возможность управлять String1 + = String2, что означает String1 = String1 + String2. – user1363061

ответ

2

Во-первых, обычно вы возвращаете новый объект из operator+, так как ожидание заключается в том, что вызов + на объект не изменяет сам объект.

MyString MyString::operator+ (const MyString& rhs) 
{ 
    // ... 

    return MyString(...); 

} 

Примечания недостающих ссылки (&) от возвращаемого типа: вы возвращаете новый объект по-копию, а не по ссылке.

Во-вторых, если вы deleteString в начале, вы не сможете скопировать его содержимое. Рассмотрим это на operator+:

char* tmp = new char[Size + rhs.Size + 1]; // +1 for the terminating '\0'  
for(int i = 0; i < Size ; i++)  
{ 
    // copy the contents of current object buffer, char-by-char 
    tmp[i] = String[i]; 
} 
for(int i = 0; i < rhs.Size+1; i++) // +1 to copy the terminating '\0' as well 
{  
    // copy the contents of other object buffer, char-by-char 
    tmp[i+Size] = rhs.String[i]; 
} 
MyString result; 
delete[] result.String; 
result.String = tmp; 
result.Size = Size+rhs.Size;  

return result; 

operator+= немного сложнее, потому что вам нужно манипулировать буфер текущего объекта:

char* tmp = new char[Size + rhs.Size + 1]; // +1 for the terminating '\0'  
for(int i = 0; i < Size ; i++)  
{  
    tmp[i] = String[i]; 
} 
for(int i = 0; i < rhs.Size+1; i++) // +1 to copy the terminating '\0' as well 
{  
    tmp[i+Size] = rhs.String[i]; 
} 
delete[] String; 
String = tmp; 
Size += rhs.Size;  

return *this; 

Обновление: Я полагаю, вы также называют delete[] в классе деструктор - которые вы должны. Также нетрудно представить, что вы захотите выполнить отбор одного объекта MyString другому. Это приведет к cosider rule of three: Если вам нужен любой из desgtructor, copy-constructor или оператор присваивания, вам, скорее всего, нужны все три.

+0

+1 для четких примеров. Однако вам нужно поменять индексы во втором цикле 'for' в каждой функции: в обоих случаях вам нужны' String [i + Size] 'и' rhs.String [i] '. –

+0

@AdamLiss - Спасибо, исправлено – Attila

+0

, когда я попробовал это, я получил следующую ошибку: MyString.cpp: 59: warning: ссылка на локальную переменную âresultâ вернулась, а выход был O! ???? – user1363061

3

Идиоматический способ - реализовать функциональность в operator+=, а затем использовать его для реализации operator+. Предположим для начала, чем ваши operator+= правильно реализован, то operator+ тривиального осуществимое как свободная функция:

MyString operator+(MyString lhs, MyString const & rhs) { 
    lhs += rhs; 
    return lhs; 
} 

Примечания: первый аргумент передается по значению, так что это копия оригинала, который мы могут быть изменены через operator+=. Есть еще несколько советов, которые могут вам пригодиться here.

Теперь вернемся к реализации operator+=. Первое, что вы должны понимать, - это то, что вам нужно выполнить: вам нужно выделить более длинный буфер, скопировать из старого буфера, добавить строку rhs, поменять старый буфера и нового (который содержит результат) и освобождает старый буфер. Порядок операций важен, если вы отпустите старое содержимое перед копированием (как вы это делаете), вы больше не можете копировать его.

// Rough approach 
MyString& operator+=(MyString const & rhs) { 
    char * new_buffer = new char[ Size + rhs.size + 1];  // [1] 
    std::copy_n(String, Size, new_buffer); 
    std::copy_n(rhs.String, rhs.Size + 1, new_buffer+Size); // [2] 
    swap(String, new_buffer);         // [3] 
    Size = Size + rhs.Size; 
    delete [] new_buffer; 
    return *this; 
} 

[1]: Выделите новый буфер и скопируйте его.Обратите внимание, что в этом конкретном случае код правильный, потому что ни одна из остальных команд в функции не может вызвать исключение. Если это не так, новый буфер должен управляться через RAII, чтобы обеспечить по крайней мере минимальную безопасность исключений.

[2]: Предполагается, что в качестве инварианта типа MyString всегда существует нулевой ограничитель. Size+1 в аргументе count копирует все элементы и нулевой ограничитель.

[3]: На данный момент были выполнены все операции, мы можем обменять старые и новые буфера, обновление размера и выпуск new_buffer (что на самом деле относится к старому буфера)

+0

Нужно ли возвращать * это? – atlex2

+0

@ atlex2: да, спасибо –