2016-08-10 3 views
1

Ich habe eine Klasse mit dem Namen HighWaterDetector:Wie übergeben Sie den Zeiger eines Klassenmembers in einer Elementinitialisierungsliste?

class HighWaterDetector 
{ 
public: 
    HighWaterDetector(Device* device); 
    Device * devicePtr; 
    Output * output1Ptr; 
    CloudMsgParser * cloudMsgParserPtr; 
    Output output1; 
    NCD2Relay ncd2Relay; 
    CloudMsgParser cloudMsgParser; 
}; 

mit Konstruktor:

HighWaterDetector::HighWaterDetector(Device* device): ncd2Relay(), output1(1, &ncd2Relay){ 
} 

Ich versuche, eine Instanz von Output in der Initialisierungsliste für HighWaterDetector aber Output zu initialisieren, die Sie übergeben müssen Zeiger auf eine Instanz von NCD2Relay, die ebenfalls ein Mitglied der Klasse HighWaterDetector ist. Mein Programm stürzt im Ausgabekonstruktor ab. Ist das der falsche Weg, dies zu tun? Was mache ich falsch?

Ausgabeklasse:

class Output 
{ 
public: 
    Output(ushort relayNum, NCD2Relay* ncd2RelayPtr); 
    ushort relayNum; 
    OutputStatus outputStatus; 
    int setOutputOn(void); 
    int setOutputOff(void); 
    void process(void); 
    NCD2Relay* ncd2RelayPtr; 
}; 


//Output Constructor 
Output::Output(ushort relayNum, NCD2Relay* ncd2RelayPtr) { 
    this->relayNum = relayNum; 
    this->ncd2RelayPtr = ncd2RelayPtr; //DOESNT CRASH IF I COMMENT THIS OUT 
    this->outputStatus.outFail = 0; 
    Serial.print("Initializing output "); 
    Serial.println(this->relayNum); 
    this->setOutputOff(); 
} 
+0

Können Sie diese Variable nicht initialisieren _in_ Konstruktor? – ForceBru

+0

Was ist los? Falsches Design. Was versuchst du mit dieser zyklischen Abhängigkeit zu erreichen? Ist es wirklich notwendig, diese Abhängigkeiten zu haben? – KIIV

+0

Ich denke nicht, dass dies ein Problem sein sollte, es sei denn, der 'Output'-Konstruktor dereferenziert 'ncd2RelayPtr'. – molbdnilo

Antwort

3

in C++ die Initialisiererliste nicht der Reihenfolge folgen, in dem Sie die Elemente in dem initializer schreiben. Es folgt vielmehr der Reihenfolge, in der die Mitglieder in Ihrer Klasse deklariert sind. Da Sie Ihre NCD2Relay nach Ihrer Output innerhalb der Klasse setzen, wird NCD2Relaynach Ausgang initialisiert, obwohl Sie in der Initialisierung NCD2Relay zuerst setzen. Also, bewegen Sie einfach NCD2Relayvor die Output innerhalb Ihrer Klassendeklaration.

+0

Sie haben mich dazu geschlagen. Das ist in der Tat die Antwort. Compiler werfen heute Fehler für diese Dinge. –

+0

Ich habe sie jetzt neu geordnet. Weißt du, warum es im Output-Konstruktor abstürzt? – Felix

+0

@Felix Es stürzt ab, weil '& ncd2Relay' nicht definiert ist, bis der Rumpf des 'HighWaterDetector'-Konstruktors gestartet wird (im Gegensatz dazu, dass er immer noch in der Initialisierungsliste für' HighWaterDetector' ist), aus dem Grund, dass grigor angegeben hat; d. h. der Konstruktor von "Output" wird aufgerufen, bevor "ncd2Relay" konstruiert wird, so dass die Referenz von "ncd2Relay" wahrscheinlich Müll ist. –

4

Haben Sie die Warnungen Ihres Compilers beachtet? oder sind sie maximal eingeschaltet? Die Reihenfolge der Deklaration Ihrer Mitglieder kann die Ursache sein:

class HighWaterDetector 
{ 
public: 
    HighWaterDetector(Device* device); 
    Device * devicePtr; 
    Output * output1Ptr; 
    CloudMsgParser * cloudMsgParserPtr; 
    Output output1;      // <- This is constructed before 
    NCD2Relay ncd2Relay;    // <- This... 
    CloudMsgParser cloudMsgParser; 
}; 

aber Konstruktor geht so:

HighWaterDetector::HighWaterDetector(Device* device): ncd2Relay(), output1(1, &ncd2Relay){ ... } 

In dem obigen Zusammenhang die Adresse ncd2Relay im Konstruktor von output1 Verwendung einfach ist Verwenden eines Zeigers auf ein nicht initialisiertes Objekt, bei dem es sich um ein nicht definiertes Verhalten handelt, wenn Sie es vor der Konstruktion dereferenzieren. Daher Sie müssen die Bestellung in Ihrer Klassendefinition erzwingen ...

gerade aus dem C++ Standard zitieren: (Hervorhebung von mir) [class.base.init/13]

In einem nicht delegieren Konstruktor Initialisierung erfolgt in der folgende Reihenfolge:

  • zuerst und nur für den Konstruktor der meisten abgeleiteten Klasse ([intro.object]), werden in der Reihenfolge virtuelle Basisklassen initialisiert sie auf einem tiefen ersten links erscheinen -Richtiges Traversal des gerichteten azyklischen Graph der Basisklassen, wobei "von links nach rechts" die Reihenfolge Aussehen der Basisklassen in der abgeleiteten Klasse Base-Specifier-Liste ist.

  • Dann werden direkte Basisklassen in der Deklarationsreihenfolge initialisiert, wie sie in der Basisspezifiziererliste erscheinen (unabhängig von der Reihenfolge der mem-Initialisierer).

  • Dann nicht-statische Datenelemente werden in der Reihenfolge initialisiert sie in der Klassendefinition deklariert wurden (wieder unabhängig von der Reihenfolge des mem-initializers).

  • Schließlich wird die Compound-Anweisung des Konstruktors ausgeführt.

+0

Das Programm stürzt immer noch ab, wenn eine Instanz von HighWaterDetector deklariert wird. – Felix

+0

@Felix, haben Sie die Deklarationen von 'output1' und' ncd2Relay' in Ihrer Klassendefinition neu angeordnet? – WhiZTiM

+0

Ja stürzt tatsächlich im Output-Konstruktor ab. Siehe oben ... Ich habe diesen Konstruktor auch gepostet. – Felix

Verwandte Themen