2013-09-26 6 views
0

프로그램 실행 시간의 시작 부분에 읽어 들여서 구문 분석하고 구조체에 넣는 구성 파일이 있습니다.const 구조체에 대한 const 정확도

내가 겪고있는 문제는이 값들이 프로그램 수명 동안 변경되어서는 안되기 때문에 이러한 구조를 일정하게 유지해야한다는 것입니다.

현재 나는 다음과 같은 일을 오전 :

config.h 파일이 잘 작동

/*-- so we don't fall out of scope --*/ 
SerialNode* global_sn; 
SerialNode local_sn = {port, format}; 
global_sn = new SerialNode(local_sn); 
SerialConfig[key_store] = global_sn; 

#pragma warning(push) 
#pragma warning(disable: 4510) /*-- we don't want a default constructor --*/ 
#pragma warning(disable: 4610) /*-- we don't want this to ever be user instantiated --*/ 

typedef struct SerialNode { 
private: 
    void operator=(SerialNode&); 
public: 
    const char* const port; 
    const char* const format; 
} SerialNode; 

#pragma warning(pop) 

typedef std::map<const char*, const SerialNode*, MapStrComp> SerialMap; 
SerialMap SerialConfig; 

config.cpp합니다. 그러나 내 문제는 지금 구조 목록을 구조 밖으로 가져 와서 수정하고 다시 넣어야하는보다 복잡한 구성 데이터를 다루고 있다는 것입니다. 이 솔루션은 뭔가 같은 것 때문에

은 물론 나는 그것을 수정할 수 없습니다 :

SerialNode* global_sn; 
SerialNode* old_sn = SerialConfig[key_store]; 
SerialNode local_sn = {port, format, old_sn->old_data, old_sn->more_old_data}; 
global_sn = new SerialNode(local_sn); 
SerialConfig[key_store] = global_sn; 
delete old_sn; 

그러나 이것은 나에게 나쁜 프로그래밍 연습을 친다. 그러한 해킹 된 솔루션을 필요로하지 않는 목적을 달성하기위한 더 좋은 방법이 있습니까? 참고로

, 나는 2010

+0

'const'를 제거 하시겠습니까? 뭔가를 만들고 const를 만들고 그 일을 해결하는 것처럼 보인다. 그러나, 제안 된 솔루션은 실제로'SerialConfig'를 수정하는 것을 제외하고는 다소 기능적인 스타일의 프로그래밍입니다. 그렇게 나쁘지는 않습니다. y r u '를 사용하여 btw? – Kal

+1

그 pragmas, 나는 그들이 당신이 생각하는 것을 의미하지 않는다고 생각합니다. 그들은 단지 다른 방법으로 돌봐야 할 경고를 단순히 억제합니다. – Thomas

+0

@Kal 그게 핵심입니다. 그것은'const'이어야하며 나는 그 것처럼 주위를 돌아 다니면 안된다. 하지만 일단 설정해야하기 때문에 설정 코드가'const'를 해결하도록 받아 들일 수 있다고 생각합니다. 다른 코드는 이것을 수정할 수 있어야합니다. – Serdalis

답변

1

간단한 대답은 토마스가 제안 것입니다 만, 제대로 (수행이 정의되지 않은 동작)의 원인이되지이다 : 변경 가능한 구성 객체를 생성하지만, 일의 나머지 부분에 전달

을 e 구성 요소를 참조하십시오. 실제 오브젝트를 작성하고 유지 보수하는 경우이를 변경할 수 있지만 나머지 어플리케이션은 구성을 수정할 수 없습니다. 과거에 사용한 일반적인 패턴은 다음과 같습니다.

class SomeObject { 
    Configuration const & config; 
public: 
    SomeObject(Configuration const & config) : config(config) {} 
    void f() { 
     if (config.someParam()) { ... 
// ... 

void loadConfiguration(Config & config) { ... } 
int main() { 
    Configuration config; 
    loadConfiguration(config); // config is a non-const &, can modify 
    SomeObject object(config); // object holds a const&, can only read 
    object.f(); 
// ... 
2

언제나처럼, 당신은되지 할 수있는 최선의 일은 이미 기록 된 것을 다시이 구현 비주얼 스튜디오를 사용하고 있습니다.

이상적으로 직렬화 프레임 워크 : C++에 대한 직렬화에 도움이되는 라이브러리와 프레임 워크의 다수가 있습니다 당신은 정확하게 r을 선택할 것입니다. 저장할 데이터 그래프를 작성하십시오. 어떤 픽스 업을했는지에 관계없이 글로벌 구성 데이터에 대한 const 액세스 만 제공하는 것이 목표 일 수 있습니다. 헤더 파일을 통해 mutator (비 const 포인터 포함)가 노출되지 않도록하십시오.

+0

나는 당신을 생각한다. 이 질문을 틀린 질문에 넣으면 여기서 직렬화가 일어나지 않습니다 : D. – Serdalis

+0

@Serdalis "구성 파일을 읽고, 파싱 한 다음 프로그램 시작시 구조에 넣습니다." –

+0

그건 직렬화가 아닙니다. 또한 파일 읽기/파싱에 문제가 없습니다. 객체에 저장하기 만하면됩니다. – Serdalis

1

이것은 귀하의 질문에 대한 답변이 아니며 귀하의 코드에 대한 일부 관찰 일뿐입니다.

  • 당신은 typedef struct SerialNode { ... } SerialNode; 필요하지 않습니다, 이것은 관용구이다. 에는 struct SerialNode { ... };으로 작성하고 SerialNode을 유형 이름으로 사용하십시오.

  • 당신이 기본 생성자를 방지하려면, 그것은 개인이 이미 char* 멤버를 사용하는 대신 std::string를 사용하지 마십시오 할당 연산자

    class SerialNode { 
    private: 
        SerialNode(); 
        SerialNode &operator=(SerialNode&); 
    ... 
    }; 
    
  • 와 마찬가지로합니다.C++ 문자열은 일반 char 포인터와 연관된 힙 할당보다 훨씬 쉽고 안전합니다.

  • 동일 키는 map에 해당합니다. std::string을 키로 사용하면 std::string이 이미 적절한 비교를 제공하기 때문에 더 이상 MapStrComp이 필요하지 않습니다.

+0

신난다 나는 C++에서 typedef가 필요 없다는 것을 깨닫지 못했다. 기본 생성자를 추가하면 내 구조체가 초기화되지 않은'non-aggregate '가됩니다. 불행히도'std :: string'을 사용하면 코드를 지원하기에는 너무 많은 변경이 필요하지만 당신은 옳습니다. – Serdalis

1

아마 더 좋은 싱글 톤 클래스 전체를 래핑하는 것입니다 :

class Config { 
    public: 
    static Config const& get() { return *config; } 
    static void load(); 

    SerialNode const* operator[](const char*); 

    private:  
    static Config* config; 

    SerialMap map; 
}; 

void Config::load() { 
    config = new Config(); 
    // put things into it 
} 

면책 조항 : 테스트하지 않으며, 한 동안 C++를 사용하지 않은, 그래서 몇 가지 구문 오류가있을 수 있습니다 :)

+0

답변의 요지는 정확하다고 생각합니다. struct에서 const를 제거하고 상위 레벨에 놓습니다. 아직도 const를 사용하는 것에 익숙해 져서 나는 지금 당장 consting을 끝냈습니다. config 객체를 전달하지만 싱글 톤이 필요하지 않습니다. 이것은 훨씬 더 큰 클래스의 일부입니다. – Serdalis

+0

'const_cast'로 const_ness를 캐스팅하고 객체에 쓰는 것은 정의되지 않은 동작입니다. 이러지 마. –

+0

감사합니다. 그 옵션을 제거했습니다. 'const_cast'가 나를 깜짝 놀라게하기 때문에 나는 그것을 몰랐다. 나는 그것을 완전히 피한다. :) – Thomas

관련 문제