2012-02-17 5 views
1

교육용으로 std :: string과 같은 클래스를 작성하려고합니다. (int)의 메서드가 문자에 대한 참조를 반환하고 인덱스가 잘못된 경우 (너무 길거나 음수 인 경우) 예외를 throw합니다. 대신 operator []가 예외를 throw하지 않습니다. 그러나 참조를 반환하므로 색인이 너무 길면 무엇을 반환합니까? 입니다 클래스는 내가 가진 :연산자 []로 문자열 클래스에 액세스

class string 
{ 
    public: 
    static const unsigned int length_max=100; 
    string(const char* field=NULL) 
    { 
     if(field!=NULL) 
     { 
      const unsigned int length=strlen(field); 
      this->field=new char[length+1]; 
      this->length=length; 
      for(unsigned int i=0;i<=length;i++) 
       this->field[i]=field[i]; 
     } 
     else 
     { 
      this->field=NULL; 
      length=0; 
     } 
    } 
    string& operator=(const char* field) 
    { 
     const unsigned int length=strlen(field); 
     if(this->field!=NULL) 
      delete this->field; 
     this->field=new char[length]; 
     this->length=length; 
     for(unsigned int i=0;i<length;i++) 
      this->field[i]=field[i]; 
     return *this; 
    } 
    string& operator= (const string& str) 
    { 
     *this=str.field; 
     return *this; 
    } 
    operator char*() 
    { 
     return field; 
    } 
    friend std::ostream& operator<< (std::ostream& out, string& str); 
    friend std::istream& operator>> (std::istream& in, string& str); 
    private: 
    char* field; 
    unsigned int length; 
}; 

std::ostream& operator<<(std::ostream& out, string& str) 
{ 
    out << str.field; 
    return out; 
} 

std::istream& operator>> (std::istream& in, string& str) 
{ 
    char temp[string::length_max]; 
    in >> temp; 
    str=temp; 
    return in; 
} 

내가 연산자 [], 나는 또한 예외를 던져 만들 수 만들고 싶어하지만, 문제는이 경우에 반환하여야한다 모르는 것입니다 색인이 너무 깁니다. 예를 들어 오퍼레이터 [] 오버로딩이있다 :

char& operator[] (int i) 
    { 
     try 
     { 
      if(i<0 || i>=length) 
       throw indexException(); 
      return field[i]; 
     } 
     catch(indexException& e) 
     { 
      std::cerr << e.what() << std::endl; 
     } 
    } 

이는 예외 :

그것은 I 그것이 할당하게 할 때문에 숯 기준 및 문자뿐만 아니라 반환한다
class indexException:std::exception 
{ 
    public: 
    virtual const char* what() 
    { 
     return "Index is either too long, or negative"; 
    } 
}; 

, 예를 들어 문자열 str이 있으면 str [5] = 'c'라고 말할 수 있습니다. 또한 예외를 처리하고 exit()를 사용하여 프로그램을 종료하지 않으려합니다. 따라서 예외가 있으면 값을 반환하지 않으며 문자열도 비어있을 수 있습니다. 무엇을 반환해야합니까? 나는 std :: string과 비슷하게 만들 것이지만 std :: string이 어떻게 구현되는지 잘 이해하지 못했다.

+1

왜 '연산자 []'안에서 예외를 잡으시겠습니까? 그것은 사용자에게 탈출하여 그들이 그것을 잡도록하십시오; 같은 장소에서 던지고 잡는 것은 목적이 없습니다. – ildjarn

+0

정의되지 않은 동작 – PlasmaHH

답변

2

동일한 블록에서 예외를 잡으려면 예외를 던지지 않는 것이 좋습니다. 함수 밖에서 오류를 던지기보다는 무언가를 반환하기를 원한다면 문을 제어하시오.

표준 문자열 클래스는 추가 된 오버 헤드가 없도록 색인에서 어떤 내용도 검사하지 않습니다. 인덱스가 범위를 벗어난 경우 내부 버퍼에서 범위를 벗어나는 인덱스를 사용하기 때문에 정의되지 않은 동작이 발생합니다.

범위를 벗어난 인덱스에 대해 반환 할 항목을 선택할 수 있습니다. 이것이 C 스타일의 문자열의 끝을 나타 내기 때문에 0이 좋은 선택 일 것입니다.

+0

0을 반환 할 수 있지만 참조를 반환합니다. 어떻게해야합니까, 새 char 할당하고 0으로 설정해야합니까? –

+0

범위 검사가 필요한 경우 예외를 throw하십시오. – rasmus

+0

@Ramy :'char &'('char const '와 반대로) 센티넬을 반환하는 것은 실제로 가능하지 않습니다. IMO는 UB 또는 예외 노선을 이용하는 것이 훨씬 낫습니다. – ildjarn