2009-10-21 2 views
4

std :: string 인수를 사용하여 클래스를 만드는 방법을 시도하고 있지만 예외를 throw하지 않고 NULL도 처리합니다. 여기에 코드의 예입니다 :C++에서 클래스는 생성자에서 const std :: string 및 매개 변수를 취할 수 있지만 NULL도 처리 할 수 ​​있습니까?

terminate called after throwing an instance of 'std::logic_error' 
what(): basic_string::_S_construct NULL not valid 
: 직관적

class myString { 
public: 
    myString(const std::string& str) : _str(str) {} 
    std::string _str; 
}; 

int main() { 
    myString mystr(NULL); 
    printf("mystr = <%s>\n", mystr._str.c_str()); 
    return 0; 
} 

,이 프로그램에서 인쇄해야한다고 생각 것 "mystr = <>"성공적으로 종료, 대신 g와 ++는이 오류를 제공합니다

이 클래스를 변경하여 logic_error 예외를 발생시키는 대신 NULL을 ""로 변환 할 수 있습니까?

(추측 할 수 있듯이 "실제"구현은이 예제보다 약간 복잡하고 _str을 사용하여 더 재미있는 일을하고 생성자에서 여러 가지 인수를 사용하여 적절하게 비공개로 유지합니다. 이 예제의 뒤에는 우리 팀의 프로그래머가 역사적인 목적으로이 문맥에서 NULL을 사용하는 경향이 있으며 컴파일러는이를 잡아 내지 못할 것입니다. 항상 ""사용하도록 재교육하는 것은 상대적으로 어렵습니다.

답변

11

가 (당신이 바로, STL의 문자열로 유형 char*의 C - 문자열을 변환 할 수 있습니까?) .

를 처리하기 위해, 당신은 당신이 특별한 것은 필요하지 않은 다른 생성자가

class myString { 
public: 
    myString(const std::string& str) : _str(str) {} 
    myString(const char* str) : _str(str==NULL?"":std::string(str)) 
    { /* and do something special in the body */ } 
    std::string _str; 
}; 

하지만, 더 나은 방법은

class myString { 
public: 
    myString(const std::string& str = "") : _str(str) {} 
    std::string _str; 
}; 
int main() { 
    myString mystr; //no() here! 
    printf("mystr = <%s>\n", mystr._str.c_str()); 
    return 0; 
} 
+2

그 코드가 악명 높은 "가장 혹독한 구문 분석"또는 이와 관련된 시나리오를 유발합니까? 보통 main()의 첫 번째 행에서와 같이 null-arg 생성자를 명시 적으로 호출하면됩니다. 나는 그것을 스스로 컴파일하려고하지 않았다. – rmeador

+0

편집 후에는 변경되지 않습니다. :-) –

+0

이것은 내가 찾고 있었던 속임수이다! const char *를 처리하기 위해 두 번째 생성자를 추가했습니다. 이 예제의 두 번째 절반은 생성자에 다른 매개 변수가 있기 때문에 제 경우에는 적용되지 않습니다 (하지만 원래는 그 사실을 알려주지 않았습니다). –

5

수 없습니다. 참조를 전달할 수있는 무언가가 있어야합니다. null 문자열 인 별명 ""을 기본값으로 사용하여이 문제를 해결할 수 있습니다. 당신이 할 수없는, 정말

class myString { 
public: 
    myString(const std::string& str) : _str(str) {} 
    explicit myString(const char* str = NULL) : _str(str?str:"") {} 
    std::string _str; 
}; 
+0

이 상황에서 필요한 '명시 적'키워드입니다? 이 예제를 명시 적으로 실행하지 않고 NULL, string ("test") 및 "test"를 전달하고 세 가지 경우 모두에서 올바른 생성자를 찾았습니다. –

+0

아니요, 순전히 방어적인 프로그래밍입니다. – dirkgently

6

: 또는

또 다른 explicit ctor에 있습니다. NULL은 문자열이 아닙니다. 당신은 문자열 인수를 생략하기 위해 생성자 과부하 수

  • :하지만 여기에 몇 가지 대안입니다.

  • 참조 대신 포인터를 사용할 수 있습니다.

  • 문자열 인수 의 기본값을 ""로 설정할 수 있습니다.

2

포인터를 인수로 사용할 수있는 생성자를 제공해야합니다. NULL은 참조가 아닌 포인터이므로 문자열 참조로 취급하려고하면 재앙이 발생합니다.

보십시오 : 실제로 여기 발생 NULLchar const*으로 해석되고 std::string로 변환 할 것을 시도되고 있음을 무엇

class myString { 
public: 
    myString(const std::string& str) : _str(str) {} 
    myString(const std::string* str) : { /* special-case logic here */} 
    std::string _str; 
}; 
+1

문제는 그가 NULL을 참조로 간주하고 있다는 것이 아닙니다. 그러나 std :: string의 생성자는 NULL을 허용하며 이것은 mystring 생성자를 호출하기 전에 임시 객체를 생성하고 시도합니다. –

0

나는이 문제로되지 않습니다 가정합니다 것입니다 추가 할 수 있습니다 당신의보기가 간단한 것처럼 보입니다.

NULL 매개 변수를 사용하는 대신 정적 변수를 만들어 할당 할 수 있습니다.

class myString { 
public: 
    static std::string nullstring; 
... 
}; 

어딘가 .CPP에서

:

std::string myString::nullstring(""); 

그리고 전화 :

int main() { 
    myString mystr(myString::nullstring); 
    printf("mystr = <%s>\n", mystr._str.c_str()); 
    return 0; 
} 
+0

그것은 sombody 실수로 NULL을 전달 중지하지 않습니다. –

+0

아마 짐작 했겠지만 실제 구현은 예제와 같이 간단하지 않으며이 특정 접근법은 문제에 매우 적합하지 않습니다 (질문에 새로 추가 된 포스트 스크립트 섹션 참조). –

+0

하지만 생성자를 수정할 수 있습니다. : 명시 적 myString (const string & str) – ebasconp

관련 문제