In meiner Anwendung habe ich eine Klasse, für die ich eine Reihe von Schnittstellen halten muss, die von der Anwendung geliefert werden.Visual Studio 2010-Debugger zeigt keine Werte bei Verwendung der Mehrfachvererbung
Da die Klasse selbst nicht alle möglichen Schnittstellen kennt, kann sie nicht einfach ein Datenelement für jede Schnittstelle behalten. Stattdessen sollte es einen Vektor von Schnittstellen behalten.
In der Praxis bedeutet dies, dass ich eine 'generische' Schnittstelle (IGeneric) definiere, von der alle spezifischeren Schnittstellen erben. Auf diese Weise kann ich immer leicht einen Vektor mit allen Schnittstellen (im Code im Folgenden habe ich die eigentliche Schnittstelle Namen von einigen Dummy-Namen ersetzt, in meiner Anwendung die Namen sind viel aussagekräftiger):
#include <vector>
#include <windows.h>
class IGeneric
{
public:
virtual ~IGeneric() {}
};
class IFirst : public IGeneric {public: virtual void one() = 0;};
class ISecond : public IGeneric {public: virtual void two() = 0;};
class IThird : public IGeneric {public: virtual void three() = 0;};
class IFourth : public IGeneric {public: virtual void four() = 0;};
typedef std::vector<IGeneric *> GenericContainer;
So installieren Sie die Schnittstellen, andere Module (die wirklich alle Schnittstellen kennen), bieten Funktionen zur Installation der Schnittstellen. Sie könnten so etwas wie dieses:
void installFirst (GenericContainer &bc, IFirst &b) { bc.push_back(&b); }
void installSecond (GenericContainer &bc, ISecond &b) { bc.push_back(&b); }
void installThird (GenericContainer &bc, IThird &b) { bc.push_back(&b); }
void installFourth (GenericContainer &bc, IFourth &b) { bc.push_back(&b); }
In practive, Anwendungen Klassen schreiben, die mehrere dieser Schnittstellen implementieren, wie folgt aus:
class DoAll : public IFirst, public ISecond, public IThird, public IFourth
{
public:
virtual void one() {}
virtual void two() {}
virtual void three() {}
virtual void four() {}
DoAll(int i) : m_i(i) {}
private:
int m_i;
};
Die Installation dieser Implementierung ist jetzt wirklich einfach. Dies ist die Hauptroutine aus meinem Beispiel:
int main() { GenericContainer gc;
DoAll alle (123);
installFirst (GC, alle); installSecond (GC, alle); installThird (gc, alle); installierenFourth (GC, alle);
DebugBreak(); }
Am Haltepunkt untersuche ich jetzt den Inhalt des Vektors im Debugger. Es sieht wie folgt aus:
Wie Sie sehen, es zeigt, dass die Umsetzung der Schnittstellen ist DoAll (in allen 4 Fällen), und es zeigt auch, wie welche Schnittstelle (iFirst, ISecond, .. .) DoAll wurde im Vektor installiert.
Problem ist, dass der Debugger scheint nicht in der Lage, den Inhalt der am weitesten abgeleiteten Klasse (DoAll) anzuzeigen. Es zeigt die Datennummer m_i, aber es kann den Wert von m_i nicht anzeigen.
Nur wenn ich explizit die erste Schnittstelle Adresse nehmen und warf ihn auf „DoAll *“, kann ich richtig den Inhalt sehen:
ich kompilieren und verknüpfen Sie die folgenden Befehle:
cl /c /EHsc /GR /Zi /Od test.cpp
link /debug test.obj
Ist dies ein Fehler in Visual Studio 2010 oder fehle ich etwas?
EDIT:
Wenn ich einzelne Vererbung, wie sie in dieser Klasse:
class DoFirst : public IFirst
{
public:
virtual void one() {}
DoFirst(int i) : m_i(i) {}
private:
int m_i;
};
Und es in den Vektor wie folgt installieren:
DoFirst f (456);
installFirst (gc,f);
Der Debugger zeigt mir die richtigen Werte und es zeigt auch sofort die abgeleitete Klasse:
Bei der Verwendung der Einzelvererbung (z. B. wenn ich eine Klasse DoFirst hinzufüge, die nur von IFirst erbt und diese mit installFirst dem Vektor hinzufügt), zeigt der Debugger mir sofort die abgeleitete Klasse und ihren Inhalt an. Bei Mehrfachvererbung geht es nur schief. Es sieht so aus, als ob Visual Studio versucht, es den Debugging-Entwicklern leicht zu machen, indem sofort die am meisten abgeleitete Klasse angezeigt wird, aber es funktioniert nicht, wenn Mehrfachvererbung verwendet wird. – Patrick
So können wir schließen, dass es eine Design-Halbfunktion des Debuggers und kein Bug ist. Ich bezweifle, dass es tatsächlich dokumentiert ist. – Dialecticus