c++ member-Funktion wird VOR constructor aufgerufen!1!elf

Gast #4837262
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.
Gast #4837276
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 :(
Gast #4838293
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.
Gast #4838370
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.)
#4838413
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.
Gast #4838466
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/

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren