Constraint-Prüfung in Konstruktorinitialisierungslisten

8

Diese Situation steht im Zusammenhang mit How to Machen Sie eine Einschränkung für die Parameter des Konstruktors , aber es ist etwas anders.

Sie möchten ein nicht standardkonstruktives Member initialisieren, müssen jedoch vor dem Erstellen nach Constraints suchen.

Beispiel:

(Bitte beachten Sie, dass dies nur ein Beispiel ist. Ob in dieser speziellen Situation nicht ganzzahlige Ganzzahlen verwendet werden sollen, ist diskussionswürdig, aber die Frage betrifft den allgemeinen Fall, in dem Sie Konstruktoren einchecken möchten)

Sie haben die folgende Klasse:

%Vor%

Der Konstruktor muss die Ganzzahlargumente auf Gültigkeit prüfen:

%Vor%

Beachten Sie, dass Buffer keinen Standardkonstruktor hat und der wahre Konstruktor noexcept ist, d. h. es gibt keine Möglichkeit, einen Fehler zu finden.

Wenn die Integer-Argumente negativ sind, hat man bereits surface_ abgesprungen. Es wäre schöner, die Bedingung zu überprüfen vor mit dem eingeschränkten Wert. Ist es möglich?

    
Sebastian Mach 23.05.2014, 13:56
quelle

3 Antworten

15

Benannter Konstruktor

Sie können einen sogenannten benannten Konstruktor verwenden (siehe auch Ссылка ), und machen Sie den Konstruktor private :

%Vor%

Benannte Konstruktoren sind interessant, falls Sie mehrere Konstruktoren haben, die möglicherweise nicht eindeutig zu verwenden sind, z. Temperatur & lt; - Celsius | Fahrenheit | Kelvin oder Entfernung & lt; - Meter | Hof | Cubit | Kilometer ... .

Andernfalls (persönliche Meinung) erzwingen sie eine unerwartete Abstraktion und auch Ablenkung und sollten vermieden werden.

Ternärer Operator und throw

C ++ erlaubt in [expr.cond] die Verwendung von throw -Ausdrücken in einem oder beiden Operanden für den ternären Operator ( ?: -operator):

%Vor%

Wenn Sie die Argumente nicht speichern, können Sie natürlich auch ?: in einem Ausdruck verwenden:

%Vor%

Oder Sie kombinieren die Vorbedingungsprüfung in einen einzelnen Operanden:

%Vor%

Die Verwendung des ?: -Operators mit einem throw -Ausdruck inline kann sehr nützlich für die Überprüfung grundlegender Integritätsregeln sein und vermeidet die Verwendung eines Standardkonstruktors (falls vorhanden) und dann "echte Initialisierung" innerhalb des Konstruktor-Körpers.

Dies kann für komplexere Szenarien ein wenig unhandlich werden.

Statisches privates Mitglied

Das Beste aus beiden Welten kann natürlich verwendet werden:

%Vor%

... oder Sie schreiben statische Funktionen für jedes Element, das Sie vorkonditionieren müssen:

%Vor%

Das ist nett, weil Sie die komplette C ++ - Maschinerie zur Verfügung haben, um die Constraint-Überprüfung durchzuführen, und zum Beispiel einfach Logging hinzufügen können. Es skaliert gut, ist aber für einfache Szenarien ein wenig weniger praktisch.

    
Sebastian Mach 23.05.2014 13:56
quelle
3

Lösung von phresnel mit inline throw und dem Vorschlag in Curgs Antwort zur Verwendung vorzeichenloser Ganzzahlen weist beide auf eine allgemeine Lösung hin: Verwenden von Typen, um sicherzustellen, dass die Werte durch Konstruktion korrekt sind.

Wenn Breite und Höhe nicht negativ sein können, empfiehlt es sich, sie ohne Vorzeichen zu erstellen. Wenn jedoch eine maximale Grenze vorhanden ist, benötigen Sie möglicherweise einen präziseren Typ zum Angeben der Invarianten, z. B .:

%Vor%

Dann könnten Sie sagen:

%Vor%

Aber dann möchten Sie möglicherweise erzwingen, dass die Breite und Höhe ein Seitenverhältnis nicht größer als 16: 9 haben. Sie können sie also in einem Size -Typ bündeln und so weiter. Auf diese Weise wurde die gesamte Validierungslogik für die Mitglieder von RenderTarget zu dem Zeitpunkt ausgeführt, an dem der Konstruktorkörper beginnt.

Diese Art der Kapselung ist grundlegend für die objektorientierte Programmierung: Die öffentliche Schnittstelle eines Objekts kann nicht verwendet werden, um sie in einen ungültigen Zustand zu versetzen, und der Konstruktor ist Teil der öffentlichen Schnittstelle.

    
Jon Purdy 25.05.2014 07:28
quelle
2

Es gibt auch die Möglichkeit, das Problem zu vereinfachen, indem Größe, Höhe und Breite ohne Vorzeichen gemacht werden, was verhindert, dass jemals ein negativer Zustand eintritt.

%Vor%

Der Konstruktor muss die Ganzzahlargumente auf Gültigkeit prüfen:

%Vor%

Zusätzliche Fehlerbehandlung:

Wenn die Verwendung des Typs zum Einschränken ungültiger Werte nicht ausreicht, gibt es viele bewährte Möglichkeiten zum Behandeln von Fehlersituationen, die über das Auslösen von Ausnahmen hinausgehen, wie zum Beispiel:

%Vor%

oder

%Vor%

oder

%Vor%

oder ...

Viele andere Alternativen.

Es gibt Vor- und Nachteile für jeden Ansatz zur Validierung von Daten, aber ich empfehle generell, die Lösung einfach genug zu halten, um sie wartbar und lesbar zu halten, da diese Lösungen oft überentwickelt werden können.

    
Curg 23.05.2014 14:09
quelle