2010-12-01 33 views
0

我有一系列的類告訴調試流(在這種情況下爲std::cout)它已經被創建,這使我能夠很好地執行程序執行。我有幾個類是不是抽象的基類的子類,當創建一個子類實例時會導致一個雙重消息。我想在從子類調用基類構造函數時抑制輸出。我知道,如果沒有一些奇特的技巧,這可能是不可能的,如果它甚至是可能的。抑制基類構造函數的輸出

我確實想過使用退格轉義序列\b,並做了足夠的工作來刪除以前的消息,但效率並不高,但它是調試信息,性能並不那麼重要,然後......)。我不確定這種方法的可移植性或有效性。

歡迎任何想法,謝謝你的努力!

回答

2

除非基礎構造函數中的代碼檢查某些條件本身,否則無法抑制基礎構造函數中的代碼。你可以通過例如傳遞一個特殊的標誌給基礎構造函數(默認值不禁止調試輸出)。

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; 
    } 
}; 

1.4.3 \b的不會幫助,如果你的輸出重定向到一個文件等

一個體面的解決辦法是建立一個虛擬函數返回一個字符串,輸出的結果功能。這不會對你的情況起作用(從構造函數中調用),因爲在基礎構造函數運行期間,虛函數的行爲就好像實例是基類型的,而不是派生的。

+0

謝謝,這看起來像最好的解決辦法,我真的不介意適應構造簽名......這似乎是一個相當簡單的解決方案。 – rubenvb 2010-12-06 14:57:51

0

其實,有一種方法,但在這種情況下,只能感謝基類直接使用std :: cout流。一個可能的解決方案是繼承的std ::流緩衝類是這樣的:需要

#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 2010-12-01 22:15:36

1

該實現解決了Vlad的一些問題。主要的區別在於構造函數簽名,它不受日誌邏輯的影響,儘管類現在是模板,這可能是可怕的,但大家都知道,那裏沒有免費的午餐。 :)所以,在這裏我們去:

#include <iostream> 

template< bool IsLeafClass = true > 
class AbstractBase 
{ 
    public: 
     AbstractBase() { 
      if (IsLeafClass) 
       std::cout << "AbstractBase" << std::endl; 
     } 
}; 

template< bool IsLeafClass = true > 
class Base : AbstractBase<false> { 
    public: 
     Base() { 
      if (IsLeafClass) 
       std::cout << "Base" << std::endl; 
     } 
}; 

typedef Base<> CBase; 

template< bool IsLeafClass = true > 
class Derived : public Base<false> { 
    private: 
     CBase _base; 

    public: 
     Derived() { 
      if (IsLeafClass) 
       std::cout << "Derived" << std::endl; 
     } 
}; 

typedef Derived<> CDerived; 

template < bool IsLeafClass = true > 
class DerivedMore : public Derived<false> { 
    private: 
     CDerived _derived; 
     CBase _base; 

    public: 
     DerivedMore() { 
      if (IsLeafClass) 
       std::cout << "DerivedMore" << std::endl; 
     } 
}; 

typedef DerivedMore<> CDerivedMore; 

int main() 
{ 
    std::cout << "logging for b" << std::endl; 
    CBase b; 

    std::cout << std::endl << "logging for d" << std::endl; 
    CDerived d; 

    std::cout << std::endl << "logging for dm" << std::endl; 
    CDerivedMore dm; 
}