2012-04-30 5 views
0

아래에 제시된 두 연산자 오버로드 함수에 대한 도움이 필요합니다. 함수 정의에서 할당을 실제로 사용하지 않고 어떻게 구현할 수 있는지 확신 할 수 없습니다. 연산자 + 내 .cpp 파일에복합 할당 및 연산자 오버로드 추가

코드 :

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

String2 += String3; 
String2.Print(); 
: MAIN.CPP에서

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

전화 :

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 파일에서 연산자

.cpp 파일 코드가 잘못되었다는 것을 알고 있습니다. 약간의 통찰력이 좋을 것입니다!

+2

(즉, 실제로 기존의 버퍼를 말한다)의 크기를 업데이트하고 new_buffer을 해제, 이전 및 새 버퍼를 교환 할 수 있습니다 문자열에 추가하려고하기 전에 문자열을 추가하지 마십시오 ... –

+0

문자열을 추가하려면 + 및 + =가 실제로 필요합니까? –

+0

두 개의 문자열 (String1 = String2 + String3 + String4가 작동하는)을 연결하려면 + 연산자가 필요하고 String1 + String2 = String1 = String1 + String2의 의미로 작동하려면 + =가 필요합니다. 명확한 예를 들면 – user1363061

답변

2

먼저 대개 operator+에서 새 개체를 반환합니다. 이는 개체에서 +를 호출해도 개체 자체가 변경되지 않기 때문입니다.

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

    return MyString(...); 

} 

참고 반환 형식에서 누락 된 참조 (&) : 당신이하지에 의해 참조에 의해 복사 새 개체를 반환합니다.

두 번째로 delete의 처음에 String 인 경우 내용을 복사 할 수 없습니다. 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 : 경고 : 지역 변수 âresultâ에 대한 참조가 반환되고 출력은 O! ???? – user1363061

3

관용적 인 방법은 operator+=에 기능을 구현 한 다음이를 사용하여 operator+을 구현하는 것입니다.

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

참고 : 올바르게 구현하여 operator+=보다 우선 가정, 다음 operator+ 무료 함수로 하찮게 구현 가능하다 그것은 우리가 원래의 사본 수 있도록 첫 번째 인수는 값에 의해 전달 operator+=을 통해 수정할 수 있습니다. 유용 할 수있는 다른 팁이 있습니다. here. , 당신은 rhs 문자열을 추가, 기존의 버퍼 복사, 더 긴 버퍼를 할당 할 필요가 이전을 교환 : 다시 operator+=을 구현하는 지금

, 당신은 이해해야하는 첫번째 것은 당신이 수행해야하는 작업은 무엇인가 buffer와 new (결과를 담고있는)를 구하여 오래된 버퍼를 비운다. 작업의 순서는 중요합니다. 이전 컨텐트를 복사하기 전에 해제하면 (작업 중에) 더 이상 복사 할 수 없습니다.

// 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] : 새 버퍼를 할당하고 복사하십시오.이 특별한 경우 코드는 이 올바른입니다. 함수의 나머지 명령어가 예외를 throw 할 수 없기 때문입니다. 그렇지 않은 경우 적어도 최소한의 예외 안전을 보장하기 위해 RAII를 통해 새 버퍼를 관리해야합니다.

[2] : 유형이 MyString 인 불변 식으로 항상 널 종결자가 있다고 가정합니다. count 인수에 Size+1은 모든 요소와 널 종결자를 복사합니다.

[3] : 모든 작업을 수행 한이 시점에서, 우리는 당신이를 삭제하는 경우

+0

* 이것을 반환해야합니까? – atlex2

+0

@ atlex2 : 예, 감사합니다. –