5

Robię prostą aplikację serwera wątków w C++, rzecz w tym, używam libconfig ++ do parsowania moich plików konfiguracyjnych. Cóż, libconfig nie obsługuje wielowątkowości, dlatego używam dwóch klas wrappera, aby wykonać "wsparcie". Chodzi o to, jeden z nich zawiedzie:Dziwny "kandydat oczekuje 1 argumentu, 0 pod warunkiem" w konstruktorze

class app_config { 
    friend class app_config_lock; 
public: 
    app_config(char *file) : 
     cfg(new libconfig::Config()), 
     mutex(new boost::mutex()) 
    { 
     cfg->readFile(file); 
    } 

private: 
    boost::shared_ptr<libconfig::Config> cfg; 
    boost::shared_ptr<boost::mutex> mutex; 
}; 

zawodzi straszliwie gdy wywołana z mojego pliku main.cpp:

app_main::app_main(int c, char **v) : argc(c), argv(v) { 
    // here need code to parse arguments and pass configuration file!. 
    try { 
     config = app_config("mscs.cfg"); 
    } catch (libconfig::ParseException &e) { 
     cout << "Parse error at line " << e.getLine() << ": " << e.getError() << endl; 
     throw; 
    } catch (libconfig::FileIOException &e) { 
     cout << "Configuration file not found." << endl; 
     throw; 
    } 
} 

i mówi:

main.cpp: In constructor ‘app_main::app_main(int, char**)’: 
main.cpp:38:54: error: no matching function for call to ‘app_config::app_config()’ 
main.cpp:38:54: note: candidates are: 
../include/app_config.h:15:5: note: app_config::app_config(char*) 
../include/app_config.h:15:5: note: candidate expects 1 argument, 0 provided 
../include/app_config.h:12:7: note: app_config::app_config(const app_config&) 
../include/app_config.h:12:7: note: candidate expects 1 argument, 0 provided 
main.cpp:41:39: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] (THIS CAN BE IGNORED, I WAS USING STD::STRING, YET CHANGED IT FOR TESTING PURPOSES) 

Co jest dziwne, bo” m wyraźnie przekazuje argument, a ponadto jest to char *!

Cóż, jak zawsze, każda pomoc zostanie doceniona.

Julian.

Odpowiedz

10

Próbujesz skonfigurować domyślnie swoją konfigurację, a następnie przypisać ją później. Ale nie masz domyślnego konstruktora.

Prawidłowy sposób przekazać argument do konstruktora zmiennej jest członkiem:

app_main::app_main(int c, char **v) : argc(c), argv(v), config("mscs.cfg") 

Można jeszcze pułapka wyjątek, za pomocą tego, co jest znane jako funkcja try-bloku. Zobacz http://www.gotw.ca/gotw/066.htm

kod końcowa:

app_main::app_main(int c, char **v) 
try : argc(c), argv(v), config("mscs.cfg") 
{ 
    // more constructor logic here 
} catch (libconfig::ParseException &e) { 
    cout << "Parse error at line " << e.getLine() << ": " << e.getError() << endl; 
    throw; 
} catch (libconfig::FileIOException &e) { 
    cout << "Configuration file not found." << endl; 
    throw; 
} 
+0

To rozwiązało problem. Jednak mam zamiar przekazać ciąg zmiennej zamiast statycznego ciągu znaków, czy jest jakiś sposób, w jaki sposób mogę przetworzyć moje zmienne argc i argv w moim elemencie app_main i zainicjować config po tym, zamiast na liście inicjowania? –

+1

@JulianBayardoSpadafora: Nie. Możesz przekazywać argumenty konstruktora do konstruktorów składowych, a nie tylko do stałych kompilujących. Możesz także wywoływać statyczne funkcje składowe na liście * ctor-initializer-list *. Wreszcie masz kontrolę nad kolejnością, w której konstruowane są elementy. Ale prawdopodobnie będziesz musiał wcześniej przetworzyć argumenty i przekazać coś w rodzaju obiektu z opcją z funkcją 'getConfigFilename()' lub taką funkcją. Lub po prostu nadaj 'app_config' funkcję odczytu pliku zamiast wykonywania go z konstruktora. –

4

Przede wszystkim, nie należy przeznaczyć muteksy dynamicznie, to niczemu nie służy. Po drugie dlatego, że masz element danych, którego nie można skonstruować domyślnie, i nie zainicjowałeś go na liście inicjującej ctor. Dodatkowo, nigdy nie przypisuj literałów łańcuchowych do zmiennych char* (powinno to być app_config(const char*), jeśli naprawdę chcesz się bawić wskaźnikami).

Twój app_main::app_main powinien wyglądać tak zamiast:

app_main::app_main(int c, char **v) try 
    : argc(c), argv(v), config("mscs.cfg") { 
} catch (libconfig::ParseException &e) { 
    cout << "Parse error at line " << e.getLine() << ": " << e.getError() << endl; 
    throw; 
} catch (libconfig::FileIOException &e) { 
    cout << "Configuration file not found." << endl; 
    throw; 
} 
Powiązane problemy