2010-06-30 6 views
3

(Qt C++) 싱글 톤 로거 클래스가있는 응용 프로그램이 있습니다. 하는 GetInstance() 구현은 다음과 같습니다C++ 싱글 톤 포인터 검사

지금 나는 .H 파일에서 매크로 다음 한
if(m_Instance == NULL) 
{ 
    try 
    { 
     m_Instance = new Logger(); 
    } 
    catch(...){} 
} 
return m_Instance; 

: -

모든 것이만큼 괜찮습니다 "#DEFINE 로그 로거 :: 인스턴스()> 로그온" new() 작업이 작동합니다. 포인터가 설정되었는지 확인하는 가장 좋은 방법은 무엇입니까 (나는 try-catch 블록을 std :: bad_alloc을 잡으려고 생각하고 있었지만 매크로에서 구현하는 방법을 모르겠습니다)? 나는 작동하는 것 같다하지만 꽤 아닌 해결 방법을 만들었습니다

"#DEFINE의 LOG 경우 (로거 :: 인스턴스()) 로거 :: 인스턴스() -> 로그인"나는 또한

내 객체에 getters/setters (예 : setPath(), getSize() ...)가 많은지 알고 싶습니다. 현재, 나는 매크로가 있습니다

"#DEFINE의 SET 설정 :: 인스턴스()"

및 코드에서

내가 ("ABC") SET-> setPath 사용할 수 있어요을; 또는 SET-> getSize();

모든 메서드에 별도의 매크로가 필요하기 때문에이 경우 내 추악한 해결 방법이 작동하지 않습니다. 어떻게 개선 할 수있는 조언?

답변 해 주셔서 감사합니다.

+0

'if'가있는 매크로는 순수한 악마입니다. 'if (error) LOG ("Error!")의 의미를 생각해보십시오. else DoImportantStuff();'. –

답변

0

이미 GetInstance 메서드에서 예외를 발견 했으므로 아무 것도 매크로에 나타나지 않습니다. 아마도 ...

if(m_Instance == NULL) 
{ 
    try 
    { 
     m_Instance = new Logger(); 
    } 
    catch (std::bad_alloc &ba) 
    { 
     // do something here... 
    } 
    catch(...){} 
} 

return m_Instance; 
+0

예외가 catch되면 m_Instance는 여전히 null이되고 매크로는 null 포인터를 역 참조하는 코드로 확장되어 추가 문제가 발생합니다. –

+1

할당에 실패하면 어떻게합니까? 오류를 기록 하시겠습니까? –

+0

좋은 질문입니다. 오류 로깅 시스템이 실패하면 어떻게합니까? –

9

끔찍한 디자인 패턴을 사용하지 마십시오. 문제가 발생하지 않습니다. 일반적으로 사람들은 좀 더 비슷한 것을 사용합니다.

Logger& Logger::GetInstance() { 
    static Logger instance; 
    return instance; 
} 

하지만 싱글 톤 패턴은 일반적으로 절대적으로 끔찍합니다. 대신 응용 프로그램 인스턴스 패턴을 사용하십시오.

+3

+1 : 왜이 ​​모든 끔찍한 싱글 톤 패턴을 사용하고 싶은지 이해할 수 없습니다. – ereOn

+0

@ereOn : 분명히 Qt가이 방향으로 인도합니다 ... 또한 싱글 톤은 쉬운 디자인 패턴 인 것처럼 보이므로 초보자는이를 기억하고 사용합니다. –

+0

싱글 톤이 때때로 사용하는 것이 좋고 다른 사람들이 그 끔찍한 시간을 가장 많이 사용한다고 말하는 이유를 이해할 수 없습니다. * 혼란 스럽네요 * – InsertNickHere

2

로그가없는 경우 수행 할 작업을 말하지 않습니다.

오류를 전파하려면 예외를 catch하거나 더 구체적인 로그를 표시하여 로그 부족을 표시하십시오.

계속 사용하려면 모든 사용에 대해 Null 검사를 수행하거나 null object pattern을 사용하여 절차 검사를 가상 방법으로 바꿉니다.

+0

null 개체 패턴 +1 - 나는 그것을 좋아한다. –

3

우선, 할당되지 않으면이 싱글 톤으로 수행중인 모든 작업을 자동으로 무시하는 것이 좋을까요? 로거와 같은 것에 대해서는 예외 메시지를보고하는 데 사용할 수 있기 때문에 오류 메시지를 던지기를 원하지 않을 수도 있습니다.

그런 경우에는 응용 프로그램이 시작될 때 (예 : 주 진입 점에서) 인스턴스 메소드를 호출하여 응용 프로그램이 성공적으로 시작되면 항상 로거를 사용하게하십시오.

마지막으로 m_instance는 boost :: scoped_ptr과 같은 것을 사용하여 메모리가 누출되지 않도록 (또는 포인터 간접 참조없이 인스턴스 메서드에서 로거를 정적 객체로 저장하기 만하면) 좋습니다. 물론 최신 운영 체제는 일반적으로 정리 작업을 시작하지만 누출 여부를 확인하기 위해 메모리 분석을 시작하면 이러한 방식으로 오탐을 많이 겪게됩니다.

매크로에 관해서는, 나는 그들이 끔찍하다고 생각하지만, 그건 내 의견이다. 당신은 매크로없이 유사한 효과를 얻을 수있다 : 심지어

void write_to_log(Logger* logger, const char* msg) 
{ 
    if (logger) 
     logger->log(msg); 
} 

나 :

void write_to_log(const char* msg) 
{ 
    Logger* logger = Logger::instance(); 
    if (logger) 
     logger->log(msg); 
} 
+0

std :: nothrow는 생성자가 던져지는 것을 멈추지 않을 것이고, 'operator new'가 던지는 것을 멈출뿐입니다. –

+0

@Joe 좋은 지적. 나는 진공 상태에서이 문제를 너무 많이 생각하고 있었다. 나는 이것을 적절히 수정할 것이다. – stinky472

+1

@ itsme1 : 메모리 누출은 메모리 누수를 테스트하는 데 문제가 될 수 있습니다. "무해한"누출을 허용하는 것은 "무해한"컴파일러 경고를 허용하는 것과 동일한 효과가 있습니다. 로그에는 너무 많은 요소가 포함되어 새로운 가능성이있는 위험 요소를 발견하지 못할 수도 있습니다. –

1

당신이 (여기 남용 것 같다) 싱글 톤 패턴에 대한 확신 경우 :

struct ILogger { 
    void Log(const char *message) = 0; 
}; 

struct NullLogger : ILogger { 
    void Log(const char *message) { } 
}; 

struct Logger : ILogger { 
private: 
    static ILogger *m_instance; 
    static const NullLogger m_null_instance; 

public: 
    void Log(const char *message) { /* ... */ } 

    static ILogger *Instance() { 
     if(m_Instance != &m_null_instance) return m_Instance; 

     try { m_Instance = new Logger(); } catch(...) { } 

     return m_Instance; 
    } 
}; 

const NullLogger Logger::m_null_instance; 
ILogger *Logger::m_instance = &Logger::m_null_instance; 

/* ... */ 
#define LOG Logger::Instance()->Log 
LOG("Hey!"); 
0

(1) 언급 된 다른 사람들이 : 싱글 톤을 사용하지 마십시오. (2) 싱글 톤을 사용하는 경우 솔리드 구현으로 사용하십시오. (3) 당신은 해킹하려면 다음과 응답에 대한

void Logger::Log(/*params*/) 
{ 
    if(NULL != this) 
    { 
    // do your logging 
    ... 
    } 
} 
+0

'#define LOG (Logger :: Instance() == NULL? Logger :: DevNull : Logger :: Instance()) -> Log' 매크로에 훨씬 깨끗한 장소가있을 때 HACK을 넣을 것입니다. 아이디어는'Logger :: DevNull-> Log (foo)'가 foo를 버린다는 것입니다. – MSalters

+0

@MSalters : Logger 클래스에서 깨 졌으므로 Logger 클래스에서 수정하십시오. –

0

감사합니다.

내 싱글 톤 구현은 웹에서 사용할 수있는 다양한 예제를 기반으로 만들어졌습니다. (예 : http://www.yolinux.com/TUTORIALS/C++Singleton.html은 내 주변에 매우 가깝습니다).

싱글 톤을 사용하는 이유는 클래스 (로거/설정)의 인스턴스가 하나뿐임을 확인하는 것입니다. 그렇습니다. 과용되는 것을 알고 있습니다.

그러나 싱글 톤을 사용하지 않고 비슷한 무언가를 구현하려고 시도한 것처럼 보입니다.