2011-01-20 2 views
20

객체 수명 기간 동안 하나의 ostream을 다른 ostream으로 리디렉션하는 클래스가 필요합니다. 몇 번 고침을 한 후에 나는 이걸 생각해 냈다 :std :: cout 리디렉션

#include <iostream> 
#include <fstream> 


class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mRedirect(inRedirect) 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::ostream & mRedirect; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    return 0; 
} 

잘 작동하는 것 같다. 나는 그것이 올바른 생각

mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 

,하지만 난 SO 커뮤니티에 확인하고 싶습니다 : 그러나, 다음 줄 모두 생성자와 소멸자에서 반복되는 이상한입니다. 이 코드에서 오류나 위험을 발견 할 수 있습니까?

편집

복사 할 수 없도록 설정하십시오.

+4

한 - 그것은 정확해야 -하지만 일반적인 측면에서 로직을 구현하는 경우 더 나은 것 'std :: cout'을 직접 호출하는 것이 아니라'std :: ostream'을 사용하십시오. –

+1

@Billy ONeal : ScopedRedirect가 일반적인 ostream으로 구현되지 않았습니까? std :: cout은 샘플에서만 사용됩니다. – StackedCrooked

+0

나는 수업이 잘못되었거나 잘못되었다고 말하는 것이 아닙니다. 나는 사실을 뒤쫓고있는 곳으로 리디렉션하는 것보다 실제로 원하는 곳으로 출력물을 보내는 것이 더 낫다고 말하고 있습니다. 즉, 어떤 특정 위치를 가리키는 std :: cout에 의존하는 코드가 cout 포인트를 변경하는 대신 리팩터링되어야한다고 말하고 있습니다. –

답변

17

이유는 그 라인이 동일하므로 버퍼를 교환하면입니다. 즉, 원래 버퍼를 리디렉션 버퍼로 바꾸면 "리디렉션"됩니다. 복원은 스왑 백입니다.

출력 스트림과 관련하여 의도 한 효과를 줄 수는 있지만 리디렉션 스트림은 이제 다른 곳으로 출력됩니다. 리디렉션은 하나의 스트림을 가져 와서 다른 곳으로 출력하는 것을 의미합니다. 이것이 '어딘가에'영향을주지 않는다는 것을 유의하십시오.

클래스가 리디렉션되지 않습니다. 실제로는 ScopedStreamSwap으로 지정해야합니다. 예를 들어, 대신이 시도 :

#include <iostream> 
#include <fstream> 

class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mRedirect(inRedirect) 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf())); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::ostream & mRedirect; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 

     // oops: 
     filestream << "also to the file, right?...nope" << std::endl; 
     filestream << "ah, why am i on the screen?!" << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    // in main, return 0 is implicit, if there is no return statement; 
    // helpful to keep in mind in snippets and short things 
} 

은 당신이 원하는 것은 이것이다 :

#include <iostream> 
#include <fstream> 

class ScopedRedirect 
{ 
public: 
    ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) : 
     mOriginal(inOriginal), 
     mOldBuffer(inOriginal.rdbuf(inRedirect.rdbuf())) 
    { } 

    ~ScopedRedirect() 
    { 
     mOriginal.rdbuf(mOldBuffer); 
    }  

private: 
    ScopedRedirect(const ScopedRedirect&); 
    ScopedRedirect& operator=(const ScopedRedirect&); 

    std::ostream & mOriginal; 
    std::streambuf * mOldBuffer; 
}; 


int main() 
{ 
    std::cout << "Before redirect." << std::endl; 
    std::ofstream filestream("redirected.txt"); 
    { 
     ScopedRedirect redirect(std::cout, filestream); 
     std::cout << "During redirect." << std::endl; 

     // yay: 
     filestream << "also to the file, right?...yes" << std::endl; 
     filestream << "i am not on the screen" << std::endl; 
    } 
    std::cout << "After redirect." << std::endl; 

    return 0; 
} 
+2

+1 재미 있고 유익한, 재미있는 예제 텍스트입니다. –

+0

수정 사항을 게시 해 주셔서 감사합니다. 나는 단순히 버퍼를 교환하고 있다는 것을 깨닫게되었지만, 나는 이상하게도 그것을 다르게 할 수 없었다. 어떤 이유로 구문이 나를 혼란스럽게합니다. – StackedCrooked