2013-05-08 7 views
8

In meiner Anwendung habe ich viele Protokolle. Ich sammle alle Fehler von allen Protokollen an einem Ort namens errorsLogger. Ich habe es auf diese Weise umgesetzt:Wie man eine variable Anzahl von Argumenten an eine andere Funktion weiterleitet?

static Logger errorsLogger; 

.... 

void Logger::Error(std::string format, ...) { 
    va_list arglist; 
    va_start(arglist, format); 

    if (this != &errorsLogger) { 
     errorsLogger.Error(format, arglist);  // how to forward parameters? 
    } 

    vfprintf(logFile, , format.c_str(), arglist); 
    fprintf(logFile, "\n"); 

    fflush(logFile); 
    va_end(arglist); 
} 

jedoch dieser Code nicht wie erwartet funktioniert errorsLogger ein wenig seltsam Strings enthält - es scheint, variable Argumente nicht übergeben wurde. Wie kann ich meinen Code reparieren?

+1

Sie benötigen eine Version von 'Error', die eine [' va_list'] (http://en.cppreference.com/w/cpp/utility/variadic/va_list) benötigt. – BoBTFish

+1

Überlegen Sie die Schnittstelle Ihres Loggers so zu ändern, dass es aussieht wie 'ostream', Sie können Dinge tun wie: 'Logger :: error() <<" die Variable x ist "<< x;' Tatsächlich 'Logger :: error() 'kann einen' ostream & 'zurückgeben – piokuc

+0

kann ich einfach einen String als ersten Schritt formatieren und dann einfach std :: string weiterleiten? – javapowered

Antwort

13

Die typische Formulierung dieses in C ist, zwei Funktionen zu haben, eine, die ... und man akzeptiert, dass ein va_list (beispielsweise im Vergleich zu printfvprintf) übernimmt. In C++ ist es praktisch, diese mit Überlastungen zu tun:

// public 
void Logger::Error(const std::string& format, ...) { 
    va_list args; 
    va_start(args, format); 
    Error(format, args); 
    va_end(args); 
} 

// private 
void Logger::Error(const std::string& format, va_list args) { 
    if (this != &errorsLogger) 
     errorsLogger.Error(format, args); 

    vfprintf(logFile, format.c_str(), args); 
    fprintf(logFile, "\n"); 
    fflush(logFile); 
} 

Verwendung von C++ 11 ist es möglich, direkt mit einer variadische Vorlage zu tun. Sie können Argumente auch an Variadic-Funktionen im C-Stil weiterleiten.

template<class... Args> 
void Logger::Error(const std::string& format, Args&&... args) {  
    if (this != &errorsLogger) 
     errorsLogger.Error(format, std::forward<Args>(args)...); 

    fprintf(logFile, format.c_str(), std::forward<Args>(args)...); 
    fprintf(logFile, "\n"); 
    fflush(logFile); 
} 
+0

Sie können definitiv variadic Vorlagen verwenden, um zu den v variadic Funktionen weiterzuleiten. [Live-Beispiel] (http://melpon.org/wandbox/permlink/0fbi8R2PCrOJkeFv) –

4

Kurz gesagt, können Sie nicht.

Alles, was Sie tun können, ist eine äquivalente Elementfunktion schreiben, die eine va_list anstelle von Variablenargumenten dauert, und übergeben Sie die initialisierte va_list down.

+0

Warum haben Sie das abgelehnt? –

+1

Vielleicht wollte jemand, dass es kürzer ist? Oder sind sie eine organische Chemikerin, die OC (OH) ₂ vorzieht? Schwer zu sagen, wirklich. –

+0

@CodyGray LOL, guter Punkt über organische Chemiker. –

0

Dafür zu arbeiten, Logger::Error hätte erklärt werden, um ein va_list als Parameter zu übernehmen, ähnlich wie vfprintf, anstatt variable Argumente in Form von ... wie fprintf.

Verwandte Themen