Seite 1 von 1

Listenerinterface der Basisklasse implementieren -> C4355

Verfasst: 13.01.2012, 10:14
von kaiserludi
Ich habe folgendes (hier veeinfach dargestelltes) Design:

Code: Alles auswählen

class Listener
{
public:
  virtual void callback(void) = 0;
};

class Base
{
public:
  Base(Listener* pListener);
private:
  Listener* mpListener;
};

class Subclass : public Base, Public Listener
{
public:
  Subclass(void);
};

Code: Alles auswählen

Base::Base(Listener* pListener)
  : mpListener = pListener
{
}

Subclass::Subclass(void)
  : Base(this)
{
}
Sprich, Subclass erbt sowohl von Base als auch von Listener, um das Callbackinterface seiner Basisklasse zu implementieren.
Die Basisklasse verlangt nun, dass man einen Pointer auf eine Implementation ihres Callbackinterfaces an ihren Konstruktor übergibt.
Die Übergabe des this-pointers an den Basisklassenkonstruktor führt allerdings in VS zum Warning C4355: "'this' : used in base member initializer list".

Da ich im Basisklassenkonstruktor nur den Pointer auf den übergebenen Listener in einer Membervariable abspeichere und sonst nicht auf die erbende Klasse zugreife, sollte das ganze problemlos funzen.

Gibt es elegantere Möglichkeiten, das Warning los zu werden, als via #pragma warning (disable : 4355 )?

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 10:47
von Schrompf
Ich bekomme die Warnung auch gelegentlich. Der Compiler warnt Dich halt, das evtl. Teile des Objekts noch nicht vollständig konstruiert sind, wenn der this-Empfänger darauf zugreift. Ich lebe bisher mit diesen Warnungen, mir ist noch kein schöner Weg drumrum eingefallen.

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 11:02
von kaiserludi
Schrompf hat geschrieben:Ich lebe bisher mit diesen Warnungen.
Das würde ich ungerne, einfach weil ich es von anderen Projekten kenne, dass ein Rebuild der Solution eben mal eine vierstellige Anzahl Warnings produziert und man immer viel Freude hat, wenn man gerade Code geschrieben hat, für den der Compiler ein weiteres generiert, welches aber in diesem Fall tatsächlich kritisch ist. Es geht in der Flut einfach unter. Daher versuche ich, die Warnings in Projekten, für die ich verantwortlich bin, gegen 0 zu halten.

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 14:18
von jumphigh
kaiserludi hat geschrieben:Daher versuche ich, die Warnings in Projekten, für die ich verantwortlich bin, gegen 0 zu halten.
Das ist vollkommen richtig so! Andere sehen sogar Warnungen als Fehler an und lassen den Code nicht durch. Ich würde an den fraglichen Stellen die Warnung einfach abstellen, wenn du dir sicher bist, dass im C'tor eben nicht auf das noch nicht vollständig konstruierte Objekt zugegriffen wird. In VC geht das mit

Code: Alles auswählen

 #pragma warning( once : 4355 ) 
direkt in der CPP vor dem C'tor.

Übrigens: Dein fehlerhaftes Beispiel findest du direkt in der Beschreibung zu C4355.

MfG
Andreas

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 15:12
von kaiserludi
Am besten wäre es wohl, wenn der Compiler das Warning erst bei einem Zugriff auf den derived-Pointer in Konstruktor oder Destruktor schmeißen würde und nicht, bereits wenns einfach nur als Parameter übergeben wird, aber das war ihnen wohl in Sachen Implementierung zu komplex.

Ja, wie bereits geschrieben, mir ist bekannt, dass ich das Warning via pragma deaktivieren kann, aber ich habe gehofft, es gibt elegantere Ansätze, als einfach das Warning auszuschalten.

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 15:27
von jumphigh
kaiserludi hat geschrieben:Am besten wäre es wohl, wenn der Compiler das Warning erst bei einem Zugriff auf den derived-Pointer in Konstruktor oder Destruktor schmeißen würde und nicht, bereits wenns einfach nur als Parameter übergeben wird, aber das war ihnen wohl in Sachen Implementierung zu komplex.
In der Tat, warum sollte man für diesen seltenen Spezialfall eine vollständige Codeanalyse (die auch nur selten möglich ist) durchführen?
Ja, wie bereits geschrieben, mir ist bekannt, dass ich das Warning via pragma deaktivieren kann, aber ich habe gehofft, es gibt elegantere Ansätze, als einfach das Warning auszuschalten.
Nein, das Warning auszuschalten ist in so einem Fall genau das richtige Mittel weil begründbar. Dies ist auch nicht unelegant.

MfG
Andreas

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 15:45
von kaiserludi
Hmm, ich frage mich gerade, was überhaupt der Nutzen dieses Warnings ist (G++ solls laut Google wohl auch nicht schmeißen). Ich könnte ja genauso gut den this-pointer nicht in der Initializer-list an den base-class Konsturktor übergeben, sondern in hinterher im Rumpf per setter setzen, dann kann zwar kein undefinierter Zugriff darauf im Konstruktor mehr passieren, aber er kann immer noch in einer Membervariablen gespeichert werden, um dann Funktionen im Base-Destruktor drauf aufzurufen, wenn der Konstruktor der abgeleiteten Klasse schon aufgerufen wurde. In dem Fall triggert das Warning aber auch nicht, obwohl die Situation nicht midner gefährlich ist.

Re: Listenerinterface der Basisklasse implementieren -> C435

Verfasst: 13.01.2012, 15:48
von dot
kaiserludi hat geschrieben:Hmm, ich frage mich gerade, was überhaupt der Nutzen dieses Warnings ist (G++ solls laut Google wohl auch nicht schmeißen). Ich könnte ja genauso gut den this-pointer nicht in der Initializer-list an den base-class Konsturktor übergeben, sondern in hinterher im Rumpf per setter setzen, dann kann zwar kein undefinierter Zugriff darauf im Konstruktor mehr passieren, aber er kann immer noch in einer Membervariablen gespeichert werden, um dann Funktionen im Base-Destruktor drauf aufzurufen, wenn der Konstruktor der abgeleiteten Klasse schon aufgerufen wurde. In dem Fall triggert das Warning aber auch nicht, obwohl die Situation nicht midner gefährlich ist.
Und wie genau sollte der Compiler dieses Verhalten detektieren? Der einzige Weg sowas zu 100% richtig zu erfassen wären Checks zur Laufzeit...

Mit Gewalt bekommt man alles kaputt, wer sowas macht ist einfach selbst schuld.