2010-12-01 11 views
0

Ich habe eine Reihe von Klassen, die den Debug Stream (std::cout in diesem Fall), dass es erstellt wurde, erzählt, so dass ich die Programmausführung schön folgen kann. Ich habe mehrere Klassen, die Unterklassen von Basisklassen sind, die nicht abstrakt sind, was zu einer doppelten Nachricht führt, wenn eine Unterklasseninstanz erstellt wird. Ich möchte die Ausgabe im Basisklassenkonstruktor unterdrücken, wenn sie von einer Unterklasse aufgerufen wird. Ich weiß, das ist wahrscheinlich ohne einen ausgefallenen Trick nicht möglich, wenn es überhaupt überhaupt möglich ist.Unterdrücken der Ausgabe von Basisklassenkonstruktor

Ich dachte an die Backspace-Escape-Sequenz \b, und tun gerade genug davon, um die vorherige Nachricht nicht wirklich effizient zu löschen, aber es ist Debug-Info, Leistung ist nicht so kritisch dann ...). Ich bin mir der Tragbarkeit oder Effektivität dieses Ansatzes nicht sicher.

Alle Ideen sind willkommen, danke für die Mühe!

Antwort

2

Es gibt keine Möglichkeit, den Code im Basiskonstruktor zu unterdrücken, es sei denn, der Code im Basiskonstruktor überprüft selbst eine Bedingung. Sie können dies z. Übergeben eines speziellen Flags an den Basiskonstruktor (mit einem Standardwert, der die Debugausgabe NICHT verbietet).

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

Ausgabe \b ‚s wird nicht helfen, wenn die Ausgabe in eine Datei umgeleitet wird usw.

Eine anständige Lösung könnte sein, eine virtuelle Funktion zu schaffen, die einen String zurückgibt, und gibt das Ergebnis, dass Funktion. Dies funktioniert jedoch nicht für Ihren Fall (Aufruf vom Konstruktor), da sich die virtuellen Funktionen während des Basiskonstruktorlaufs so verhalten, als ob die Instanz vom Basistyp ist, nicht abgeleitet.

+0

Danke, das sieht aus wie die beste Lösung, ich habe nicht wirklich etwas dagegen die angepasste Konstruktor Signatur ... es scheint wie eine recht einfache Lösung. – rubenvb

0

Eigentlich gibt es einen Weg, aber in diesem Fall nur dank der Tatsache, dass die Basisklassen den std :: cout-Stream direkt verwenden. Eine mögliche Lösung ist std :: streambuf Klasse wie folgt erben:

#include <iostream> 
#include <streambuf> 

class DummyStreambuf : public std::streambuf {}; 

Dieser Schritt ist erforderlich, da std :: streambuf Konstruktor geschützt sind. Wenn Sie DummyStreambuf haben (oder wie immer Sie es nennen), müssen Sie nur den Stream-Puffer im Standard-Stream std :: cout ändern.

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

Natürlich gibt es hier Raum für Verbesserungen. Sie könnten einen einfachen Singleton schreiben, der die Ausgabe von std :: cout ein- und ausschalten könnte. Hier ist eine mögliche Implementierung für single-threaded Umgebung:

#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

Wie würde es abgeleiteten Klasse-CToren erlauben, Ausgaben zu schreiben und zu verhindern, dass Basis-CTOs dies tun? – foraidt

+0

std :: cout hat eine externe Verknüpfung und ist für eine Programminstanz einzigartig. Wenn Sie den std :: cout-Stream ändern, ändern Sie ihn für jeden Client-Code. Um rubenvb zu zitieren: "Ich habe eine Reihe von Klassen, die den Debug-Stream (std :: cout in diesem Fall) erzählt, dass es erstellt wurde, so dass ich die Programmausführung schön folgen kann." – LavaScornedOven

+0

(1) Wenn die Basisklasse einige Member als Teil ihres Konstruktors initialisiert, wird ihre Ausgabe ebenfalls unterdrückt. (2) Ihre Lösung erfordert den Aufruf von' CoutSwitch :: turnOff() 'vor jeder Instanz einer abgeleiteten Klasse; (3) Ich sehe nicht, wie diese Lösung auf den Fall erweitert werden kann, wenn eine weitere Klasse von der abgeleiteten Klasse abgeleitet ist – Vlad

1

Diese Implementierung adressiert einige der Bedenken von Vlad. Der Hauptunterschied liegt in der Konstruktorsignatur, die nicht von Loglogik beeinflusst wird, obwohl Klassen jetzt Vorlagen sind, was beängstigend sein könnte, aber wie Sie alle wissen, gibt es kein kostenloses Mittagessen da draußen. :) Also, hier gehen wir:

Verwandte Themen