2013-04-12 3 views
-4

사람 등록을위한 프로그램을하고 있고 연산자 = 오버로드 문제가 있습니다.오버로드 = C++ 더 많은 구조

클래스 CRegister, 구조체 PersonPlace이 있습니다.

struct Places{ 
    char date[11]; 
    char * street; 
    char * city; 

Places & operator = (const Places & other){ 
     delete [] street; 
     delete [] city; 

     strncpy (date, other.date, 11); 

     int len; 
     len = strlen(other.street); 
     this->street = new char[len]; 
     strncpy (this->street, other.street, len); 

     len = strlen(other.city); 
     this->city = new char[len]; 
     strncpy (this->city, other.city, len); 

     return *this; 
    } 
} 


struct Person{ 
    char id[12]; 
    char * name; 
    char * surname; 
    Places ** oldPlaces; 

    int placesCount; 
    int placesSize; 
}; 

Person & Person::operator =(const Person& other){ 
    for (int i = 0; i < this->placesSize; i++){ 
     delete this->oldPlaces[i]; 
    } 
    delete [] this->oldPlaces; 
    delete [] name; 
    delete [] surname; 


    placesCount = other.placesCount; 
    placesSize = other.placesSize; 

    oldPlaces = new Places*[other.placesSize]; 

    strncpy (id, other.id, 11); 

     int len; 

     len = strlen(other.name); 
     this->name = new char[len]; 
     strncpy (this->name, other.name, len); 

     len = strlen(other.surname); 
     this->surname = new char[len]; 
     strncpy (this->surname, other.surname, len); 

    for (int i = 0; i < placesCount; i++){ 
     oldPlaces[i] = other.oldPlaces[i]; 
    } 

    return *this; 
} 



class CRegister  
{ 
    private: 
    Person **persons; 
    int personCount; 
    int personSize; 
}; 

CRegister& CRegister::operator =(const CRegister& other){ 
    for (int i = 0; i < this->personSize; i++){ 
     delete this->persons[i]; 
    } 
    delete [] this->persons; 

    personCount = other.personCount; 
    personSize = other.personSize; 

    persons = new Person*[other.personSize]; 

    for (int i = 0; i < personCount; i++){ 
     persons[i] = other.persons[i]; 
    } 


    return *this; 
} 

그러나 코드가 컴파일되었지만 넷빈즈가 실행 실패를 표시합니다. 왜?

+1

일부 연산자는 오버로드 될 수 없습니다. = 그것들 중 하나입니다. – CapelliC

+5

@CapelliC 음, 뭐야?!? 물론'operator ='** **에 과부하가 걸릴 수 있습니다. – Angew

+1

1.'std :: string'을 사용하십시오. 2. 이익. –

답변

1

Rule of Three을 따르지 않습니다. 그것은 유일한 이유가 아닌 한 가지 이유 일 수 있습니다. 다른 주에

,

  • 이유는 단순히 std::string를 사용할 수 있습니까?
  • 왜 사용하지 않습니까? copy and swap idiom?
2
len = strlen(other.city); 
    this->city = new char[len]; 
    strncpy (this->city, other.city, len); 

이 문자열의 길이를 보존하지 않습니다. 나중에 this->city의 길이를 어떻게 알 수 있습니까?

+0

그래서 '\ 0'의 마지막 위치 인 len + 1을 작성해야합니까? –

+0

그건 편도 일 겁니다. 'std :: string'을 사용하면 더 이해할 수 있습니다. –

+0

숙제이며 불행히도 문자열을 사용할 수 없습니다 ... –

1

기본적으로 C (래핑 된 클래스)를 사용하고 있으므로 은 C 코드에서 가장 자주 발생하는 오류 일 수 있습니다. strlen이 아니고이 아닌 인 '\0' 인 문자열의 문자 수를 반환합니다. strcpy 복사 최종 '\0', 그래서 한 번 더 문자 (당신은 어떻게 당신이 안하는) 당신은, 당신은하지 '\0' 종료되는 문자열로 종료됩니다 strncpy를 사용하는 경우. 따라서 strcpy을 사용하면 버퍼의 끝을 오버런하고 strncpy을 사용하면 문자열을 읽는 모든 사용자가 버퍼 끝을 오버런합니다 ( 은 '\0'까지 계속됩니다).

규칙은 strlen 수익률보다 한 번 더 문자를 할당하는 것입니다.

size_t len = strlen(other.name) + 1; 
name = new char[ len ]; 
strcpy(name, other.name); 

(하지 표준 C, 많은 시스템은 물론, malloc를 사용하여이 작업을 수행하는 strdup 기능 이 있지만, 것입니다 당신은 너무 . 코드가 A의 객체를 떠나 : deletefree와 함께 무료로 이 아닌) 그 너머

를, 내가 전에 말을 반복 할 것이다 n 할당 중 하나라도 실패하면 n 일관성없는 상태입니다. 항상은 수업에서 수정하기 전에 을 실패 할 수있는 모든 작업을 수행합니다. 스왑 관용구 operator= 고전 이지만, 그렇지 않으면 지역 포인터를 사용할 수 있습니다 : 그것은 오류 처리 코드의 모든 복제 을 가진 피할 수 있기 때문에,

char* newName = NULL; 
char* newSurname = NULL; 
Places* newPlaces = NULL; 

try { 
    newName = strdup(other.name); 
    newSurname = strdup(other.surname); 
    newPlaces = deapCopyPlaces(other.places); 
} catch (...) { 
    deepDelete(newPlaces); 
    delete [] newName; 
    delete [] newSurname; 
} 
// And only now... 
deepDelete(places); 
delete [] name; 
delete [] surname; 
name = newName; 
surname = newSurname; 
places = newPlaces; 

그러나 스왑 관용구가 지금까지보다 더 낫다입니다.

관련 문제