我有一系列的类告诉调试流(在这种情况下为std::cout
)它已经创建,允许我很好地遵循程序执行。我有几个类是基类的子类,它们不是抽象的,在创建子类实例时会产生双重消息。我想在从子类调用它时抑制基类构造函数中的输出。我知道如果没有一些花哨的技巧,这可能是不可能的,如果它甚至可能的话。
我确实考虑过使用退格转义序列\b
,并且正在做足够的事情来删除以前的消息并不是真正有效的,但它的调试信息,性能并不是那么关键......)。我不确定这种方法的可移植性或有效性。
欢迎任何想法,谢谢你的努力!
答案 0 :(得分:2)
除非基础构造函数中的代码检查某些条件本身,否则无法抑制基本构造函数中的代码。你可以通过例如将特殊标志传递给基础构造函数(默认值为NOT禁止调试输出)。
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;
}
};
如果您的输出被重定向到文件等,输出\b
将无济于事。
一个不错的解决方案可能是创建一个返回字符串的虚函数,并输出该函数的结果。然而,这不适用于您的情况(从构造函数调用),因为在基本构造函数运行期间,虚函数的行为就好像实例是基类型而不是派生的。
答案 1 :(得分:1)
这项实施解决了弗拉德的一些担忧。主要区别在于构造函数签名,它不受日志记录逻辑的影响,虽然类现在是模板,这可能很可怕,但是众所周知,那里没有免费的午餐。 :)所以,我们走了:
#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;
}
答案 2 :(得分:0)
实际上,有一种方法,但在这种情况下,只是因为基类直接使用std :: cout流。一种可能的解决方案是继承std :: streambuf类,如下所示:
#include <iostream>
#include <streambuf>
class DummyStreambuf : public std::streambuf {};
这一步是必需的,因为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;
}