2010-12-01 6 views
0

디버그 스트림 (이 경우 std::cout)이 생성되었음을 알리는 일련의 클래스가있어서 프로그램 실행을 잘 수행 할 수 있습니다. 서브 클래스 인스턴스가 생성 될 때 이중 메시지를 생성하는 추상 클래스가 아닌 기본 클래스의 서브 클래스 인 여러 클래스가 있습니다. 서브 클래스에서 호출 될 때 기본 클래스 생성자에서 출력을 억제하고 싶습니다. 나는 이것이 가능하다 할지라도 아마도 약간의 멋진 트릭 없이는 이것이 가능하지 않을 수 있음을 안다.기본 클래스 생성자의 출력을 억제합니다.

나는 백 스페이스 escape sequence 을 사용하고, 이전의 메시지를 삭제하는 것만으로는 충분하지 않다고 생각했지만, 디버그 정보이기 때문에 성능은 그렇게 중요하지 않습니다 ...). 이 방법의 이식성이나 효율성에 대해서는 확신 할 수 없습니다.

모든 아이디어를 환영합니다. 노력해 주셔서 감사합니다.

답변

2

기본 생성자의 코드가 일부 조건 자체를 검사하지 않는 한 기본 생성자의 코드를 억제 할 방법이 없습니다. 예를 들어 기본 생성자에 특수 플래그를 전달합니다 (기본값은 디버그 출력을 금지하지 않음). 당신의 출력을 파일로 재 지정된 경우 도움이되지 않습니다 \b 년대를 출력하기

class Base 
{ 
    public: 
    Base(bool suppressDebugInfo = false) 
    { 
     if (!suppressDebugInfo) 
      cout << "hallo from base" << endl; 
    } 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(bool suppressDebugInfo = false) : Base(true) 
    { 
     if (!suppressDebugInfo) 
      cout << "hallo from derived" << endl; 
    } 
}; 

괜찮은 솔루션은 가상 문자열을 반환 기능, 출력이 결과를 만들 수 기능. 그러나 기본 생성자 실행 중에 가상 함수가 인스턴스가 파생되지 않은 기본 형식 인 것처럼 동작하므로 생성자에서 호출하는 경우에는 작동하지 않습니다.

+0

고마워,이 최고의 솔루션처럼 보이는데, 나는 정말로 적응 된 생성자 서명을 신경 쓰지 않는다 ... 아주 솔직한 해결책처럼 보인다. – rubenvb

0

실제로이 방법에는 기본 클래스가 std :: cout 스트림을 직접 사용한다는 사실 만 있습니다. 한 가지 가능한 솔루션은 다음과 같이 표준 : streambuf의 클래스를 상속하는 것입니다 : 표준 : streambuf의 생성자가 보호되기 때문에

#include <iostream> 
#include <streambuf> 

class DummyStreambuf : public std::streambuf {}; 

이 단계가 필요합니다. DummyStreambuf (또는 다른 이름을 붙이면), std :: cout 표준 스트림에서 스트림 버퍼를 변경하기 만하면됩니다.

int main() 
{ 
DummyStreambuf dummy; 

std::cout << "test" << std::endl; 

// save default stream buffer for later use 
std::streambuf *buff = std::cout.rdbuf(&dummy); 

// this line shouldn't print 
std::cout << "test" << std::endl; 

// restore default stream buffer 
std::cout.rdbuf(buff); 

std::cout << "test" << std::endl; 
} 

물론 여기에는 개선의 여지가 있습니다. 당신은 std :: cout 출력을 켜고 끌 수있는 간단한 싱글 톤을 쓸 수 있습니다. 다음은 단일 스레드 환경을위한 구현 중 하나입니다.

#include <iostream> 
#include <streambuf> 

class DummyStreambuf : public std::streambuf {}; 

class CoutSwitch 
{ 
private: 
    DummyStreambuf _dummyBuf; 
    std::streambuf *_coutBuf; 

    CoutSwitch() : _coutBuf(std::cout.rdbuf()) {} 

    static CoutSwitch &instance() { 
    static CoutSwitch _instance; 
    return _instance; 
    } 

public: 
    static void turnOn() { 
    std::cout.rdbuf(instance()._coutBuf); 
    } 

    static void turnOff() { 
    std::cout.rdbuf(&instance()._dummyBuf); 
    } 
}; 

int main() 
{ 
std::cout << "test" << std::endl; 

CoutSwitch::turnOff(); 

std::cout << "test" << std::endl; 

CoutSwitch::turnOn(); 

std::cout << "test" << std::endl; 
} 
+0

어떻게 파생 클래스 CTors가 출력을 작성하고 기본 클래스 CTors가 그렇게하지 못하게 할 수 있습니까? – foraidt

+0

std :: cout은 외부 연결을 가지고 있으며 프로그램 인스턴스에 고유합니다. std :: cout 스트림을 변경하면 클라이언트 코드가 변경됩니다. rubenvb를 인용하려면 : "디버그 스트림 (이 경우에는 std :: cout)이 생성되었음을 알리는 일련의 클래스가 있으므로 프로그램 실행을 잘 수행 할 수 있습니다." – LavaScornedOven

+0

(1) 기본 클래스가 일부 멤버를 생성자의 일부로 초기화하면 해당 출력도 억제되며 (2) 솔루션에서 파생 클래스를 인스턴스화하기 전에'CoutSwitch :: turnOff() '를 호출해야합니다. (3) 파생 클래스에서 파생 된 클래스가 하나 더있을 때 어떻게이 솔루션을 확장 할 수 있는지 알지 못합니다. – Vlad

1

이 구현은 블라드의 우려 사항 중 일부를 다룹니다. 가장 큰 차이점은 생성자 시그니처에 있으며, 로깅 로직의 영향을받지 않습니다. 클래스는 템플릿이므로 지금은 무서울 수도 있지만 모두 알고 있듯이 무료 점심은 없습니다. :) 그럼, 여기에 우리가 간다 :

관련 문제