2013-03-08 2 views
3

저는 구조 중에 두 개의 const char* 문자열을 연결해야하고 나중에 초기화 목록에서 결과 (연결된 문자열)를 사용해야하는 클래스가 있습니다.안전하게 클래스 생성자에서 C- 문자열을 연결하십시오.

const char* SUFFIX = "suffix"; 

class widget { 
public: 
    widget(const char* prefix) : key(???), cls(key) { }; 

private: 
    const char* key; 
    const important_class cls; 
} 

widget("prefix_"); // key should be prefix_suffix 

는 글로벌있다 (에 widget의 CPP) 나는 사용자가 제공 한 접두사에 추가 할 const char* 접미사.

어떻게 만드시겠습니까?


BTW. 나는 에 대해 들었습니다. 당신이 const char*이 필요하면, 당신은 여전히 ​​const char*를 반환하는 key.c_str()를 callng하여 얻을 수

const std::string SUFFIX = "suffix"; 

class widget { 
public: 
    widget(std::string const & prefix) 
      : key(prefix + SUFFIX), cls(key) 
    { }  // ^^^^^^^^^^^^^^concatenation! 

private: 
    const std::string key; 
    const important_class cls; 
} 

widget("prefix_"); 

: 나는 string를 사용할 수 있다면 나는 약 const char*

+6

'std :: string'(또는 프로젝트에서 사용하는 문자열 클래스)을 사용해야합니다. 그렇게하면 훨씬 쉽게되고 예외를 피할 수 있습니다. – JoergB

+0

** 왜 ** 당신은'string'을 사용할 수 없습니까? 여러분의 클래스는'string'의 관점에서 그것을 쓰더라도'const char *'를 기꺼이 받아 들일 것입니다 : http://liveworkspace.org/code/3eDEfw$4 – us2012

+0

이것은'C++와'클래스가 아닌'C++입니다. –

답변

2

사용 std::string : 여기에 코드에

const char* SUFFIX = "suffix"; 

class widget { 
public: 
    widget(const char* prefix) : 
    intermediate(string(prefix) + suffix), 
    key(intermediate.c_str()), 
    cls(key) { 
    } 

private: 
    const std::string intermediate; 
    const char* key; 
    const important_class cls; 
} 

widget("prefix_"); // key should be prefix_suffix 

유일한 것은 다른는 intermediate 전용 멤버 변수입니다.

std::string 개체 인 intermediate은 연결을 유지하는 데 필요한 동적 메모리를 관리합니다. 예외, 할당, 복사 등의 문제가 발생했을 때 청소가 잘됩니다. string이 변이되지 않은 한 const char*c_str()에 의해 반환되는 한 유효한 상태로 유지되는 한 string이 변이되지 않은 한 계속 정리됩니다. intermediateconst이므로 돌연변이 기능을 호출 할 수 없기 때문에 내부 버퍼를 사용하여 cls에 문제가 없어야합니다.

const char* SUFFIX = "suffix"; 

class widget{ 
public: 
    widget(const char* prefix) : key(std::string(prefix) + suffix), cls(key.c_str()) 
    {} 

private: 
    std::string key; 
    const important_class cls; 
}; 

두, 이런 정적 초기화 기능, 뭔가를 사용 : keystd::string A와

+0

그리고'중간 '은'key'가 가리키는 메모리를 해제 할 것인가? – Xlaudius

+0

@Xlaudius 예'intermediate'는 올바르게 정리할 것이고,'key'는 다른 것을 가리킬 수 없습니다. 'intermediate'는'important_class'와'key' 후에 소멸 될 것이므로 적어도 필요한만큼 존재할 것입니다. –

+0

하지만'c_str'가 보유한 문자열의 복사본을 반환 할 가능성이 없으므로 잘라낸 부분에서 위젯의 인스턴스를 삭제 한 후에 누출 될 수 있습니까? – Xlaudius

3

std::string를 사용하여이 문제를 간단한 작업을 만들고, 여기에 묻지 것 . 그래서 귀하의 경우, 그것은 C- 문자열"prefix_suffix" 줄 것입니다.

또한 선언의 순서가 제대로 한 적이있는 중요 참고 : 그 건설 key에 따라 달라집니다로 clskey를 선언해야합니다.

+0

예. 그게 아니라 질문 : ( – Xlaudius

+0

회원들에게'key'와'cls'에 대한 주문 의존성을 강조하기위한 코멘트가 있어야합니다. – JoergB

+0

@JoergB : 괜찮습니다. 순서는 맞습니다. – Nawaz

0

문자열을 함께 사용하면 std::string을 사용하는 것이 더 좋습니다. 필요한 경우 으로 전화하여 const char*을받을 수 있습니다. std::string::append은 인수로 const char*도 가져옵니다. 또는 + -operator를 사용하십시오. 을 참조하십시오.

0

초기화 목록에서 그렇게 할 수 있을지 확신하지 못합니다. 확실히 더 많은 경험을 가진 다른 사용자는 물론, 이것은 명백한 들릴지 ...이 도움이 될 수 있지만 표준 : : 문자열을 사용하고 바로 갈 수 있습니다 : 물론

class widget 
{ 
    public: 
    widget(const char* prefix) : key(prefix) 
    { 
     string_key.append(suffix); 
    }; 

    private: 
    const char* key; 
    std::string string_key; 
}; 

, 당신은 다만 수

class widget 
{ 
    public: 
    widget(const char* prefix) : key(prefix) 
    { 
     key.append(suffix); 
    }; 

    private: 
    std::string key; 
}; 

전체 "important_class"부분이 누락되었습니다. 여기는 무엇을 나타내는가? 너는 무엇을 이루려고 하느냐?

희망이 있습니다.

1

std :: string (또는 프로젝트에서 사용하는 문자열 클래스)을 사용해야합니다. 그렇게하면 훨씬 쉽게되고 예외를 피할 수 있습니다. 당신이 주장하는 경우

,

widget(const char* prefix) : 
    key(strcat(strcpy(new char[strlen(prefix)+strlen(SUFFIX)+1], prefix), SUFFIX)), 
    cls(key) { } 

은 그것을 C의 방법으로 할 것이다.

important_class의 생성자는 예외를 throw해서는 안됩니다.

결과로 key을 사용하여 cls을 초기화해야하는 경우에는 선언 순서를주의해야합니다. 중간 값으로

0

나는 값 지속성 등

하나, 상점에 대한 사용자의 요구에 따라, 두 가지 옵션을 볼 수

const char* SUFFIX = "suffix"; 

class widget{ 
public: 
    widget(const char* prefix) : key(concat_(prefix, suffix)), cls(key) 
    {} 

private: 
    const char* key; 
    const important_class cls; 

    static const char* concat_(const char* a, const char* b) 
    { 
    std::string val(a); 
    val += b; 
    char* ret = new char[val.size() + 1]; 
    strcpy(ret, val.c_str()); 
    return val; 
    } 
}; 
0

처음에는 이론적 인 퀴즈처럼 보였지만 ST가없는 임베디드 플랫폼이있을 수 있습니다. 엘.
어쨌든 구식 C 스타일의 함수 strlen, strcpystrcat을 사용해야합니다.
클래스를 사용하고 있으므로 컴파일러에서 new 연산자를 지원한다고 가정합니다. 내가 여기에 최종 코드를 작성하기 전에 당신이 문자열을 연결하기 위해 수행해야 할 단계는 다음과 같습니다

const char* key; 
key = new char[strlen(prefix) + strlen(SUFFIX) + 1]; 
strcpy(key, prefix); 
strcat(key, SUFFIX); 
... 
delete [] key; 

다행히 모두의 strcpy 및 대상을 반환 strcat와.
는 무료 잊지 마세요 :) ...

#include <string.h> 

class widget { 
public: 
    widget(const char* prefix) 
    : key(strcat(strcpy(new char[strlen(prefix) + strlen(SUFFIX) + 1], prefix), SUFFIX)) 
    , cls(key) { }; 

private: 
    const char* key; 
    const important_class cls; 
}; 

가이 코드를 디버깅하지 못했지만, 그것이 오히려 지저분 해 보이지만, 잘 컴파일 : 여기
그리고 당신의 코드를 볼 수있는 방법입니다 버퍼를 소멸자에 넣는다.
행운을 빌어 요!

관련 문제