Подавить вывод из конструктора базового класса - PullRequest
0 голосов
/ 01 декабря 2010

У меня есть серия классов, которая сообщает потоку отладки (std::cout в данном случае), что он был создан, что позволяет мне хорошо следить за выполнением программы. У меня есть несколько классов, которые являются подклассами базовых классов, которые не являются абстрактными, что приводит к двойному сообщению при создании экземпляра подкласса. Я хотел бы подавить вывод в конструкторе базового класса, когда он вызывается из подкласса. Я знаю, что это, вероятно, невозможно без какого-то хитрого трюка, если вообще возможно.

Я действительно думал об использовании escape-последовательности возврата на обратную сторону \b, и достаточно просто сделать это, чтобы удалить предыдущее сообщение не очень эффективно, но это отладочная информация, производительность не так критична ...) Я не уверен в мобильности или эффективности этого подхода.

Любые идеи приветствуются, спасибо за усилия!

Ответы [ 3 ]

2 голосов
/ 01 декабря 2010

Нет способа подавить код в базовом конструкторе, если только код в базовом конструкторе сам не проверяет некоторые условия.Вы можете достичь этого, например, передав специальный флаг базовому конструктору (имеющему значение по умолчанию, НЕ запрещающее вывод отладки).

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 голос
/ 04 декабря 2010

Эта реализация решает некоторые проблемы Влада. Основное отличие заключается в сигнатуре конструктора, которая не зависит от логики ведения журнала, хотя классы теперь являются шаблонами, что может быть пугающим, но, как вы все знаете, бесплатного обеда там нет. :) Итак, поехали:

#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;
}
0 голосов
/ 02 декабря 2010

На самом деле, есть способ, но в этом случае, только благодаря тому, что базовые классы напрямую используют поток 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...