Forum: PC-Programmierung c++ member-Funktion wird VOR constructor aufgerufen!1!elf


von Rasputin (Gast)


Lesenswert?

Hallo Forum,

Ich verstehe mal wieder die Welt nicht.

Ich konnte mittels Debugger nach verfolgen, dass hier zuerst 
onDestroy(this, onDestroyAccessor) aufgerufen wird und erst 
anschliessend onDestroyAccessor(). Und das sowohl in einer richtigen 
Klasse, als auch in dieser Testklasse. WARUM???
1
class Test {
2
public:
3
  EventHandle<Test> onDestroy;
4
5
  Test() :
6
    onDestroyAccessor(),
7
    onDestroy(this, onDestroyAccessor) {
8
    printf("Test()\n");
9
  }
10
11
  void destroy() {
12
    onDestroyAccessor.trigger();
13
  }
14
15
private:
16
  EventHandle<Test>::Accessor onDestroyAccessor;
17
};
18
19
int main() {
20
  Test test;
21
  test.destroy();
22
}

Ausschnitt aus der EventHandle-Klasse:
1
template <class T>
2
class EventHandle {
3
public:
4
  class Accessor;
5
  friend class Accessor;
6
7
  EventHandle(T *const obj_, Accessor &accessor_) : obj(obj_) {
8
    accessor_.assignHandle(this);
9
  };
10
// ... etc...
11
}
12
13
template <class T>
14
class EventHandle<T>::Accessor {
15
public:
16
  friend EventHandle;
17
  Accessor() : event_handle(nullptr) { }
18
19
private:
20
  void assignHandle(typename EventHandle::ptr_t event_handle_) {
21
//    assert(!event_handle); <--- schlägt fehl weil constructor nicht aufgerufen wurde!
22
    event_handle = event_handle_;
23
  }
24
25
  virtual void trigger() {
26
//    assert(event_handle); <--- schlägt ebenfalls fehl, weil der constructor
27
//                               event_handle anschliessend wieder auf nullptr gesetzt hat.
28
    event_handle->trigger();
29
  }
30
// ... etc...
31
}

Vielen Dank schon mal für jeden Kommentar.

von Sebastian V. (sebi_s)


Lesenswert?

Die Reihenfolge von Memberintialisierung ist durch die Reihenfolge der 
Member in deiner Klasse gegeben, nicht durch die Reihenfolge in der 
Initializer List. AFAIK gibt GCC da auch ne Warnung.

von Rasputin (Gast)


Lesenswert?

Danke für den Tipp. Probier ich gleich. Bei VC++2015 gibt's übrigens 
keine Warnung.

von Rasputin (Gast)


Lesenswert?

DU BIST EIN GENIE! Da wär ich echt im Leben nicht drauf gekommen! Ist 
auch irgendwie extrem unlogisch.
D.h. ich muss bei dieser Klasse die privaten Member immer vor den 
öffentlichen deklarieren. Unschön :(

von Sebastian V. (sebi_s)


Lesenswert?

Es gibt ja keine Regel das es nur einen public oder private Bereich 
geben darf. Du kannst also so viele Bereiche machen wie du brauchst.

von tictactoe (Gast)


Lesenswert?

Rasputin schrieb:
> Ist auch irgendwie extrem unlogisch.

Nun ja, Destruktoren der Members müssen in umgekehrter Reihenfolge der 
Konstruktoren aufgerufen werden. Da der Destruktor der Klasse als 
einzigen Hinweis die Anordnung der Members in der Klasse hat, muss sich 
der Konstruktor auch nach diesem Hinweis richten. "Logischerweise" 
arbeitete der Konstruktor von oben nach unten in der Member-Liste, und 
der Destruktor von unten nach oben.

von Horst (Gast)


Lesenswert?

Rasputin schrieb:
> Bei VC++2015 gibt's übrigens keine Warnung.
Tu dir selbst einen gefallen und benutz was richtiges zur 
Programmierung. Die warnen dann auch sinnvoll.

von MaWin (Gast)


Lesenswert?

Horst schrieb:
> benutz was richtiges zur
> Programmierung.

Und was ist deiner werten Meinung nach "richtig"?

von Rasputin (Gast)


Lesenswert?

@tictactoe

Guter Hinweis! Das hab ich nicht bedacht. So gesehen ergibt das 
natürlich absolut Sinn.

Horst schrieb:
> Rasputin schrieb:
>> Bei VC++2015 gibt's übrigens keine Warnung.
> Tu dir selbst einen gefallen und benutz was richtiges zur
> Programmierung. Die warnen dann auch sinnvoll.

Ich hab bis vor kurzem cygwin mit gcc benutzt. Aber fand es dann albern. 
Entweder richtig Linux in einer VM oder den offiziellen Compiler von 
Microsoft für Windows.

Aber es ist schon wahr. Wenn ich in Visual Studio /Wall einstelle, 
bekomme ich fast 150 Warnungen, etwa 90% in der Art von

> "int printf(const char *const ,...)": Funktion ist nicht "inline"

alles Warnungen die den std Namensraum betreffen.

Sowie einige

> "foo": 2 Bytes Abstand hinter Datenmember "foo::bar" hinzugefügt.

aber zu dem Fehler steht nirgends etwas. (oder ich kann es in dem Wulst 
von Warnungen nichts sehen.)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rasputin schrieb:
>> "foo": 2 Bytes Abstand hinter Datenmember "foo::bar" hinzugefügt.
>
> aber zu dem Fehler steht nirgends etwas.

Das ist fehlerhaft übersetzt.  Korrekt gedeutscht heißt die Meldung:
1
 "foo": 2 Oktette Abstand hinter Datenmitglied "foo::bar" hinzugefügt.

Wobei Puristen anstatt "Oktette" lieber "Achtlinge" verwenden.

von Rolf M. (rmagnus)


Lesenswert?

Rasputin schrieb:
> Horst schrieb:
>> Rasputin schrieb:
>>> Bei VC++2015 gibt's übrigens keine Warnung.
>> Tu dir selbst einen gefallen und benutz was richtiges zur
>> Programmierung. Die warnen dann auch sinnvoll.
>
> Ich hab bis vor kurzem cygwin mit gcc benutzt. Aber fand es dann albern.
> Entweder richtig Linux in einer VM oder den offiziellen Compiler von
> Microsoft für Windows.

Es gibt ja auch noch mingw. Das versucht nicht gleich, eine komplette 
Un*x-Umgebung unter Windows nachzubilden, sondern bietet einfach eine 
GNU-Toolchain zum bauen von Windows-Programmen.

von heiligsbeitle (Gast)


Lesenswert?

Rasputin schrieb:
> Ich hab bis vor kurzem cygwin mit gcc benutzt. Aber fand es dann albern.
> Entweder richtig Linux in einer VM oder den offiziellen Compiler von
> Microsoft für Windows.

[Ziemlich OT]
Ich verfüttere meinen Code regelmäßig sicherheitshalber auch an GCC und 
Clang (und Valgrind und ...). Seit Windows 10 ist das wegen des 
Linux-Subsystems noch einfacher geworden: Den Entwicklermodus aktivieren 
und in Powershell ein Mal
1
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
ausführen, fertig. Ok, in einer VM kann man ohne Fummelei (*) GUIs 
testen etc.

(*)
http://www.howtogeek.com/261575/how-to-run-graphical-linux-desktop-applications-from-windows-10s-bash-shell/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.