2017-11-18 9 views
2

Ist es möglich, etwas über die Parameter für eine Klasse Konstruktor zu behaupten, bevor die Initialisierung Liste genannt wird?Wie können Aussagen vor einer Klasseninitialisierungsliste platziert werden?

class Foo 
{ 
    int m_lower; 
    int m_upper; 
    unsigned int m_delta; 

    public: 
    Foo(int t_lower, int t_upper) : 
     assert(t_lower < t_upper), // Assert here, before initialisation of fields. 
     m_lower(t_lower), 
     m_upper(t_upper), 
     m_delta(t_upper - t_lower) 
    { 
     // Assert could be made here, but m_delta would have underflowed if t_upper < t_lower. 
    } 
} 

Der Vorteil eines assert vor der Initialisierung Liste wäre, dass die Anforderungen für die Initialisierung der einzelnen Felder sofort vorgenommen werden könnten, und würden nicht möglicherweise mehrere Male bei jeder Initialisierung, die die gleichen Anforderungen hat überprüft werden müssen. Während der Initialisierung des m_delta in einem init_delta Initialisierung Verfahren hergestellt werden kann, wenn mehrere Werte die gleiche Anforderung haben, die t_upper > t_lower dann die Assertion in jedem zu gesetzt haben würde (einhüllen eine vorherige Behauptung wird entfernt). Wenn sie in der Konstruktfunktion selbst platziert wird, ist die Initialisierung eines oder mehrerer Felder möglicherweise bereits fehlgeschlagen (mit etwas dramatischerem als einem Unterlauf).

Wenn es oben in der Initialisierungsliste platziert wird, ist der Vertrag für den Benutzer bei der Prüfung frei und würde einen Fehler anzeigen, bevor Fehler auftreten, wie z. B. Unterlauf in diesem Fall.

Der obige Fall ist nur ein vereinfachtes Beispiel des Problems. Ich weiß, dass es bessere Möglichkeiten gibt, das oben genannte Problem zu lösen (abs() usw.).

Vielen Dank für Ihre Hilfe und Beratung!

+0

Die typische assert, das heißt von , wird 'Abbruch' die App. Daher denke ich, dass es keinen Vorteil gibt, wo immer Sie das behaupten. IMHO, die meisten Ihrer Leser erwarten nützliche Behauptungen im Körper des CTOR. Einige mögen die Behauptung bevorzugen, bevor sie den ctor aufrufen. –

Antwort

3

Sie können die Komma-Operator verwenden:

public: 
    Foo(int t_lower, int t_upper) : 
     m_lower(assert(t_lower < t_upper), t_lower), 
     m_upper(t_upper), 
     m_delta(t_upper - t_lower) 
    { 
     ... 
    } 

Operanden des Komma-Operator sind von links nach rechts ausgewertet, und der richtige Wert wird als Ergebnis verwendet.

Beachten Sie, dass die Reihenfolge der Initialisierungen in der Reihenfolge an, dass die Elementvariablen in der Klasse deklariert sind, nicht die Reihenfolge, in der Initialisierungsliste. Sie sollten also den Aufruf assert() in die Initialisierung der ersten Elementvariablen eingeben.

+0

Danke für den Komma Hinweis, ich war mir dieser Funktion nicht bewusst! Dies erfordert jedoch immer noch eine Bestätigung für jedes Feld, das die gleiche Assertion erfordert. – Arc

+0

Nein, tut es nicht. Sie müssen es nur in die erste Elementvariable einfügen. – Barmar

+0

Ist 'assert' garantiert als Ausdruck verwendbar? – Angew

Verwandte Themen