2013-05-08 10 views
8

W mojej aplikacji mam dużo dzienników. Łączę wszystkie błędy ze wszystkich dzienników w jednym miejscu o nazwie errorsLogger. I zostały wdrożone to w ten sposób:jak przekazać zmienną liczbę argumentów do innej funkcji?

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

Jednak ten kod nie działa zgodnie z oczekiwaniami errorsLogger zawiera trochę dziwne ciągi - wydaje się zmienne argumenty nie została podjęta. Jak naprawić mój kod, aby był ważny?

+1

Trzeba wersję 'Error' który zajmuje [' va_list'] (http://en.cppreference.com/w/cpp/utility/variadic/va_list). – BoBTFish

+1

Zastanów się nad zmianą interfejsu twojego loggera tak, aby wyglądał jak 'ostream', będziesz mógł robić takie rzeczy jak:' Logger :: error() << "zmienna x jest" << x; 'W rzeczywistości' Logger :: error() 'może zwrócić' ostream & ' – piokuc

+0

czy mogę po prostu sformatować ciąg znaków jako pierwszy krok, a następnie po prostu przesyłać dalej ciąg std :: string? – javapowered

Odpowiedz

13

Typowy preparat ten w C ma dwie funkcje: jeden, który przyjmuje ... i który przyjmuje va_list (np printf porównaniu vprintf). W C++ jest to wygodne to zrobić z przeciążeniem:

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

Korzystanie C++ 11, możliwe jest, aby zrobić bezpośrednio ze zmiennej liczbie argumentów szablonu. Możesz także przekazywać argumenty do funkcji variadycznych w stylu C.

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

Możesz zdecydowanie użyć szablonów variadic do przekazania do funkcji variadycznych C. [Przykład na żywo] (http://melpon.org/wandbox/permlink/0fbi8R2PCrOJkeFv) –

4

Krótko mówiąc, nie można.

Wszystko, co możesz zrobić, to napisać równoważną funkcję składową, która pobiera va_list zamiast argumentów zmiennych i przekazać zainicjowane va_list w dół.

+0

Dlaczego lekceważysz to? –

+1

Może ktoś chciał, żeby był krótszy? A może to chemik organiczny, który woli pisać OC (OH) ₂? Trudno powiedzieć, naprawdę. –

+0

@CodyGray LOL, dobry punkt o chemikach organicznych. –

0

Do tego do pracy, Logger::Error musiałaby zostać uznana zaakceptować va_list jako parametr, podobnie jak vfprintf zamiast zmiennych argumentów w postaci ... jak fprintf.

Powiązane problemy