C ++ - Konstruktor, einer für Grad, einer für Radiant

7

Was wäre die beste Vorgehensweise in C ++, um zwei separate Konstruktoren zu definieren, von denen einer in Grad und der andere im Bogenmaß eingegeben wird? Das Problem, das ich es auf die direkte Weise mache, ist, dass die Signatur beider Methoden dem Compiler gleich aussieht, obwohl die Parameternamen identifizieren, welches was ist, und der Compiler einen re-declaration Fehler kennzeichnet. Ist das möglich, ohne ein anderes Feld einzuführen?

Ich kann es mit einem einzelnen Konstruktor machen, indem ich einen zusätzlichen bool-Parameter hinzufüge, der es erlaubt, auszuwählen, welche Einheiten übergeben werden, und ein if im Körper zu verwenden.

    
gone 20.07.2017, 16:46
quelle

6 Antworten

14

Verwenden Sie das benannte Konstruktor-Idiom . Machen Sie Ihren Konstruktor privat und wählen Sie den Argumenttyp, Grad oder Bogenmaß. Dann machen Sie entsprechend benannte statische Member-Funktionen, die die notwendige Konvertierung durchführen.

%Vor%     
Benjamin Lindley 20.07.2017 16:52
quelle
6
  

Was wäre die beste Vorgehensweise in C ++, um zwei separate Konstruktoren zu definieren, von denen einer in Grad und der andere in Radianten eingegeben wird?

Die beste Vorgehensweise wäre, nur einen Konstruktor zu haben, der eindeutig nur einen von ihnen verwendet (wahrscheinlich Radiant, da alle trigonometrischen Funktionen mit Radianten arbeiten).

Sie sollten zusätzliche Funktionen haben, um die Werte zu konvertieren. Eine Möglichkeit besteht darin, benutzerdefinierte Literale 1 zu verwenden.

Diese sollen einfachen Werten einen Kontext mit einer bestimmten zu verwendenden Einheit geben.

Ich würde den folgenden Weg gehen:

%Vor%

1 Die Beispiele aus der Dokumentation haben sogar eine Möglichkeit, Grad in Radianten umzurechnen.

    
user0042 20.07.2017 16:48
quelle
3

Ich schlage einen Ansatz wie

vor %Vor%

Beachten Sie, wie wir die Konstruktoren für Radians und Degrees explizit gemacht haben. Dadurch wird verhindert, dass sie implizit aufgerufen werden, sodass der Benutzer seine Absicht erklären muss.

Nun, in diesem Fall, implizite Konstruktion wie

%Vor%

würde zu einem Mehrdeutigkeitsfehler führen, der jedoch bei vielen Iterationen von API-Releases möglicherweise nicht zutrifft.

Wenn wir zum Beispiel die Sichtbarkeit eines der Angle -Konstruktoren entfernt oder geändert haben, würde der obige Code ohne Fehler kompilieren.

Die explicit -Konstruktoren für Degrees und Radians verhindern diese Gefahr und machen den Code klarer.

Wir können benutzerdefinierte Literale als syntaktischen Zucker über diese Typen hinzufügen, um eine engere Notation zu ermöglichen.

Zum Beispiel:

%Vor%

und

%Vor%

aktivieren

%Vor%

und

%Vor%

bzw.

Dies funktioniert aufgrund der erweiterten conexpr-Funktionen in den letzten Versionen der Sprache. Da wir unsere Konstruktoren als kompilierzeit-auswertbar gekennzeichnet haben, können sie als Literaltypen verwendet werden. Beachten Sie, dass meine Literale möglicherweise von long double auf double abgeschnitten werden, und ich muss erst noch lernen, warum sie mindestens in MSVC 19.11.25505 als long double deklariert werden müssen.

Aktualisierung:

Nachdem ich die anderen Antworten durchgelesen hatte, die mir sehr gut gefallen haben (danke an alle), wurde mir klar, dass viel mehr Zeit für die Kompilierung benötigt wurde. Daher fügte ich eine etwas überarbeitete Implementierung hinzu, die etwas von dem, was ich gelernt habe, enthielt. Es ist auch leichter als meine vorherige Version und verwendet keine Accessoren.

Die obige Implementierung ist die überarbeitete Version.

    
Aluan Haddad 20.07.2017 17:09
quelle
1

Benjamins Vorgehensweise variiert:

%Vor%     
Aconcagua 20.07.2017 17:03
quelle
1

Eine Option ist die Verwendung von Disambiguierungs-Tags .

%Vor%

Definieren Sie dann Ihre Konstruktoren:

%Vor%

Und rufe so auf:

%Vor%

Obwohl sie oberflächlich der "named factory" -Lösung ähneln, sind Disambiguierungs-Tags mit Dingen wie perfekter Weiterleitung und neuer Platzierung kompatibel. Zum Beispiel:

%Vor%     
Joseph Thomson 20.07.2017 17:37
quelle
1

Ich werde zu Beginn sagen, dass dies eine schwerere Herangehensweise ist, aber Sie können eine strenge Trennung von Grad und Bogenmaß in Ihrer gesamten Anwendung vornehmen, indem Sie opake Typdefinitionen verwenden. Dies würde ein versehentliches Mischen von Werten mit verschiedenen Einheiten verhindern - sie werden zu Kompilierungsfehlern anstatt zu Laufzeitfehlern. Ich habe eine opake typedef-Bibliothek , die es einfach macht, numerische opake typedefs zu erstellen und die erlaubten Operationen auszudrücken auf sie.

Sie können separate Grad- und Radianten-Typen mit Gradwerten, die in Radianten umwandelbar sind, wie folgt machen:

%Vor%     
Kyle Markley 20.07.2017 19:19
quelle

Tags und Links