Methode überladen



  • Hallo zusammen,

    möchte eine Methode überladen, aber leider klappt das nicht so ganz wie ich mir das dachte 😕

    #include <iostream>
    using namespace std;
    
    class A{
      public:
        void doSomething(bool test) {
          cout << "only bool" << endl;
        }
    
        void doSomething(string test, bool test1=true) {
          cout << "string and bool" << endl;
        }
    };
    
    int main() {
      A a;
      a.doSomething(true);
      a.doSomething("test");
      a.doSomething((string) "test");
    
      return 0;
    }
    

    Hätte hier erwartet, dass der 2. Aufruf "string and bool" zurückgibt, aber leider kommt "only bool". Der 3. Aufruf funktioniert dann wieder, aber das ist nicht praktikabel.

    Gibt es eine Möglichkeit, dass es richtig erkannt wird oder muss ich die Methode umbenennen?



  • entweder:

    using namespace std::literals;
    
    a.doSomething("test"s);
    

    oder:

    template <typename T>
    typename std::enable_if <std::is_same <T, bool>::value>::type doSomething(T test) {
      // include utility, type_traits
      cout << "only bool" << endl;
    }
    

  • Mod

    overload schrieb:

    Gibt es eine Möglichkeit, dass es richtig erkannt wird oder muss ich die Methode umbenennen?

    Wenn es exakt so sein soll, wie du hier gezeigt hast, dann geht es logischerweise nicht wie gewünscht, denn das was du gezeigt hast, funktioniert schließlich nicht wie gewünscht. Die eigentliche Frage ist daher, was du dir wirklich wünscht. Was willst du genau erreichen? Insbesondere: Welcher Grad von Abweichung von dem Code, den du gezeigt hast, ist ok? Ist so etwas wie von 5cript gezeigt in Ordnung für dich?



  • Das mit den literals ist mir etwas zu gefährlich. Wenn das mal einer vergisst ...

    Habe noch nicht viel mit templates gearbeitet. Wie würde das denn in meinem code aussehen?

    Wenn ich einfach meine bool Methode damit überschreibe bekomme ich einige Fehlermeldungen.

    overload.cpp:9:19: error: 'enable_if' in namespace 'std' does not name a type
    overload.cpp:9:29: error: expected unqualified-id before '<' token
    overload.cpp: In function 'int main()':
    overload.cpp:23:21: error: no matching function for call to 'A::doSomething(bool)'
    overload.cpp:23:21: note: candidate is:
    overload.cpp:14:10: note: void A::doSomething(std::string, bool)
    overload.cpp:14:10: note:   no known conversion for argument 1 from 'bool' to 'std::string {aka std::basic_string<char>}'
    

  • Mod

    type_traits eingebunden? C++11 aktiviert?



  • versteh ich auch nicht, wieso er hier nicht durch function matching die zweite methode auswählt...



  • Danke, hat funktioniert.



  • Sewing schrieb:

    versteh ich auch nicht, wieso er hier nicht durch function matching die zweite methode auswählt...

    const char* -> bool

    — a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and



  • Ist klar,
    bei doSomething() hast du einmal nur einen bool und einmal einen String und einen bool.
    Beim Funktionsaufruf für doSomething(String, bool) übergibst du nur einen String. Wenn du also noch einen bool hintendran hängst, müsste es klappen

    Mfg
    BOSS2000



  • Und warum dann nicht einfach

    void doSomething(const char *test, bool test1=true)
    {
        cout << "string and bool" << endl;
    }
    

    ???

    Und wenn du dann noch explizit 'string' haben möchtest (damit man dann nicht immer .c_str() anhängen muß):

    void doSomething(string test, bool test1=true)
    {
        doSomething(test.c_str(), test1);
    }
    

    (natürlich bessere Parameternamen wählen)



  • Ist das nicht ziemlicher umständlicher C-Style?



  • Sewing schrieb:

    Ist das nicht ziemlicher umständlicher C-Style?

    Was genau?
    A a;a.do_Something statt do_Something? Nee, das ist zielich umständlicher Java-Stil.

    Das Problem hier ist, daß kein Mensch weiß, welche Bedeutung do_Something haben soll und der Plan dieser Überladung schon verwerflich war und hier nur gefragt wurde, wie man diesen verwerflichen Plan verwirklichen kann.

    Übrigens richten Default-Parameter bloß Schaden an. Ich benutze keine, seit 25 Jahren viel weniger Default-Parameter als zum Beispiel gotos (außer vielleicht als Tags in SFINAE-Szenarien). Und beim Debuggen fremden Codes nach dem Hochziehen auf maximale Compilerwarnstufe sind Defaultparameter die Ursache numero uno für die schmerzhaftesten Facepalms.

    bool convertUnicode(char *ours,char* theirs,bool to=from);
    

    Der bool-Rückgabetyp ist blöd oder fraglich, wird von den Pr0ggern eh nicht abgefragt.
    ours und theirs sind Kacknamen, stattdessen sollten sie beschreiben, welcher der beiden nun char und welcher uint16_t drin hat.
    Außerdem sollten sie im Typ beschreiben, welcher was drin hat.
    Unicode ist ein Kackname, wenn UCS2 gemeint ist.
    Und const sollte dem Parameter gegeben werden, der nur gelesen wird.
    Soweit war das ALTER C-Stil (in C schreibt man auch schon lange nicht mehr so nen Müll, aber Tatsache, es war mal üblich so).
    Dann kamen unsere C++-Experten und führten den Parameter ein, der aus convertFromUnicode eine convertToUnicode macht, statt zwei neue Funktionsnamen einzuführen. Einmal Cobol, immer Cobol. Und trotzdem könnte man damit leben. Das sind noch Soft-Facepalms.

    Aber der Default-Parameter ist dann der Todesstoß. Den sieht man beim Debuggen des aufrufenden Codes nicht.


Log in to reply