2010-12-01 31 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; 
}