Arbeiten mit C++-Code im Klassen-Designer

Der Klassen-Designer enthält eine visuelle Entwurfsoberfläche, ein sogenanntes Klassendiagramm, die die Codeelemente in Ihrem Projekt visuell darstellt. Sie können mit Klassendiagrammen Klassen und andere Typen in einem Projekt entwerfen und visualisieren.

Der Klassen-Designer unterstützt folgende C++-Codeelemente:

  • Klasse (ähnlich eine verwalteten Klassenform, außer dass sie mehrere Vererbungsbeziehungen haben kann)

  • Anonyme Klasse (zeigt den von der Klassenansicht generierten Namen für den anonymen Typ an)

  • Vorlagenklasse

  • Struktur

  • Enum

  • Makro (zeigt die Ansicht des Makros nach der Verarbeitung an)

  • TypeDef

Hinweis

Dies ist nicht identisch mit dem UML-Klassendiagramm, das Sie in einem Modellierungsprojekt erstellt können. Weitere Informationen finden Sie unter UML-Klassendiagramme: Referenz.

C++Klassen in Klassen-Designer

Der Klassen-Designer unterstützt C++-Klassen und visualisiert native C++-Klassen auf die gleiche Weise wie Visual Basic- und C#-Klassenformen, mit Ausnahme, dass C++-Klassen über mehrere Vererbungsbeziehungen verfügen können. Sie können die Klassenform erweitern, um mehr Felder und Methoden in der Klasse anzuzeigen, oder sie aus Platzgründen reduzieren.

Hinweis

Der Klassen-Designer unterstützt keine Unions (eine spezielle Klasse, bei der der zugeordnete Arbeitsspeicher nur so groß wie der größte Datenmember der Union ist).

Einfache Vererbung

Wenn Sie mehr als eine Klasse in ein Klassendiagramm ziehen, und die Klassen verfügen über eine Klassenvererbungsbeziehung, werden sie durch einen Pfeil verbunden. Der Pfeil zeigt in Richtung der Basisklasse. Wenn z.B. die folgenden Klassen in einem Klassendiagramm angezeigt werden, werden sie durch einen Pfeil verbunden, der von B nach A zeigt:

class A {};
class B : A {};

Sie können auch nur Klasse B in das Klassendiagramm ziehen: Klicken Sie mit der rechten Maustaste auf die Klassenform für B, und klicken Sie dann auf Basisklassen anzeigen. Dadurch wird die Basisklasse angezeigt: A.

Mehrfachvererbung

Der Klassen-Designer unterstützt die Visualisierung der Vererbungsbeziehungen mehrerer Klassen. Mehrfache Vererbung wird verwendet, wenn eine abgeleitete Klasse Attribute von mehr als einer Basisklasse hat. Es folgt ein Beispiel für mehrfache Vererbung:

class Bird {};
class Swimmer {};
class Penguin : public Bird, public Swimmer {};

Wenn Sie mehr als eine Klasse in das Klassendiagramm ziehen, und die Klassen verfügen über eine Vererbungsbeziehung mehrerer Klassen, werden sie durch einen Pfeil verbunden. Der Pfeil zeigt in Richtung der Basisklassen.

Durch einen Rechtsklick auf eine Klassenform und anschließend durch Klicken auf Basisklassen anzeigen, wird die Basisklasse für die ausgewählte Klasse angezeigt,

Hinweis

Der Befehl Abgeleitete Klassen anzeigen wird für C++-Code nicht unterstützt. Sie können abgeleitete Klassen anzeigen, indem Sie zur Klassenansicht wechseln, den Typknoten erweitern, den Unterordner Abgeleitete Typen erweitern und anschließend diese Typen in das Klassendiagramm ziehen.

Weitere Informationen über die Vererbung von mehreren Klasse finden Sie unter Mehrfachvererbung und Mehrere Basisklassen.

Abstrakte Klassen

Der Klassen-Designer unterstützt abstrakte Klassen (auch als „abstrakte Basisklassen“ bezeichnet). Dies sind Klassen, die nicht instanziiert, aber von denen andere Klassen abgeleitet werden können. Wenn Sie ein Beispiel aus „Mehrfachvererbungs“ weiter oben in diesem Dokument verwenden, können Sie womöglich die Bird-Klasse als einzelne Objekte wie folgt instanziieren:

int main()
{
   Bird sparrow;
   Bird crow;
   Bird eagle;
}

Sie können jedoch nicht die Swimmer-Klasse als einzelnes Objekt instanziieren. Sie können nur andere Tierklassen davon ableiten, z.B. Penguin, Whale und Fish. In diesem Fall müssten Sie die Swimmer-Klasse als eine abstrakte Basisklasse deklarieren.

Um eine Klasse als abstrakt zu deklarieren, können Sie das Schlüsselwort abstract verwenden. Als abstrakt markierte Member oder Member in einer abstrakten Klasse sind virtuell und müssen von Klassen, die von der abstrakten Klasse abgeleitet wurden, implementiert werden.

class Swimmer abstract
{
   virtual void swim();
   void dive();
};

Eine Klasse kann auch als abstrakt deklariert werden, indem mindestens eine rein virtuelle Funktion eingeschlossen wird:

class Swimmer
{
   virtual void swim() = 0;
   void dive();
};

Beim Anzeigen dieser Deklarationen in einem Klassendiagramm werden der Klassenname Swimmer und dessen rein virtuelle Funktion swim als kursiv in einer abstrakten Klassenform zusammen mit der Bezeichnung Abstrakte Klasse angezeigt. Beachten Sie, dass die Typform der abstrakten Klasse identisch mit einer normalen Klasse ist, außer dass der Rahmen eine gepunktete Linie ist.

Eine von einer abstrakten Klasse abgeleitete Klasse muss jede rein virtuelle Funktion in der Basisklasse überschreiben, oder die abgeleitete Klasse kann nicht instanziiert werden. In diesem Fall muss z.B. bei der Ableitung einer Fish-Klasse von der Swimmer-Klasse, Fish die swim-Methode überschreiben:

class Fish : public Swimmer
{
   void swim(int speed);
};

int main()
{
   Fish guppy;
}

Wenn dieser Code in einem Klassendiagramm angezeigt wird, zeichnet der Klassen-Designer eine Vererbungslinie von Fish zu Swimmer.

Anonyme Klassen

Der Klassen-Designer unterstützt anonyme Klassen. Anonyme Klassentypen sind Klassen, die ohne Bezeichner deklariert werden. Sie können keinen Konstruktor oder Destruktor besitzen, können nicht als Argumente oder Funktionen übergeben werden und können nicht als Rückgabewerte von Funktionen zurückgegeben werden. Sie können eine anonyme Klasse verwenden, um einen Klassennamen durch einen TypeDef-Namen wie im folgenden Beispiel zu ersetzen:

typedef struct
{
    unsigned x;
    unsigned y;
} POINT;

Strukturen können auch anonym sein. Im Klassen-Designer werden anonyme Klassen und Strukturen auf die gleiche Weise wie der entsprechende Typ angezeigt. Obwohl Sie anonyme Klassen und Strukturen deklarieren und anzeigen können, verwendet der Klassen-Designer nicht den von Ihnen angegebenen Tagnamen. Es wird der Name verwendet, der von der Klassenansicht generiert wird. Die Klasse oder Struktur wird in der Klassenansicht und im Klassen-Designer als ein Element namens __unnamed angezeigt.

Weitere Informationen zu anonymen Klassen finden Sie unter Anonyme Klassentypen.

Vorlagenklassen

Der Klassen-Designer unterstützt die Visualisierung von Vorlagenklassen. Geschachtelte Deklarationen werden unterstützt. Die folgende Tabelle zeigt einige Standarddeklarationen.

Codeelement Ansicht „Klassen-Designer“
template <class T>

class A {};
A<T>

Vorlagenklasse
template <class T, class U>

class A {};
A<T, U>

Vorlagenklasse
template <class T, int i>

class A {};
A<T, i>

Vorlagenklasse
template <class T, template <class K> class U>

class A {};
A<T, U>

Vorlagenklasse

Die folgende Tabelle zeigt einige Beispiele für die teilweise Spezialisierung.

Codeelement Ansicht „Klassen-Designer“
template<class T, class U>

class A {};
A<T, U>

Vorlagenklasse
template<class T>

class A<T, T> {};
A<T, T>

Vorlagenklasse
template <class T>

class A<T, int> {};
A<T, int>

Vorlagenklasse
template <class T1, class T2>

class A<T1*, T2*> {};
A<T1*, T2*>

Vorlagenklasse

Die folgende Tabelle zeigt einige Beispiele der Vererbung in der partiellen Spezialisierung.

Codeelement Ansicht „Klassen-Designer“
template <class T, class U>

class A {};

template <class TC>

class A<T, int> {};

class B : A<int, float>

{};

class C : A<int, int>

{};
A<T, U>

Vorlagenklasse

B

Klasse

(zeigt auf Klasse A)

C

Klasse

(zeigt auf Klasse A)

Die folgende Tabelle zeigt einige Beispiele für die partielle Spezialisierung von Vorlagenfunktionen.

Codeelement Ansicht „Klassen-Designer“
class A

{

template <class T, class U>

void func(T a, U b);

template <class T>

void func(T a, int b);

};
A

func<T, U> (+ 1 overload)
template <class T1>

class A {

template <class T2>

class B {};

};

template<> template<>

class A<type>::B<type> {};
A<T1>

Vorlagenklasse

B<T2>

Vorlagenklasse

(B ist in Klasse A unter geschachtelte Typen enthalten)
template <class T>

class C {};

class A : C<int> {};
A

Klasse

-> C<int>

C<T>

Vorlagenklasse

Die folgende Tabelle zeigt einige Beispiele der Vorlagenvererbung.

Codeelement Ansicht „Klassen-Designer“
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

class A : C<int>::B {};
A

Klasse

->B

C<int>

Klasse

(B ist in Klasse C unter geschachtelte Typen enthalten )

C<T>

Vorlagenklasse

Die folgende Tabelle zeigt einige Beispiele der kanonischen spezialisierten Klassenverbindung.

Codeelement Ansicht „Klassen-Designer“
template <class T>

class C {};

template<>

class C<int> {};

class A : C<int> {};

class D : C<float> {};
A

Klasse

->C<int>

C<int>

Klasse

C<T>

Vorlagenklasse

D

Klasse

->C<float>
class B {

template <class T>

T min (const T &a, const T &b);

};
B

min <T>

C++-Enumerationen im Klassen-Designer

Der Klassen-Designer unterstützt enum-Typen von C++ und bewertete enum class-Typen. Dies ist ein Beispiel:

enum CardSuit {
   Diamonds = 1,
   Hearts = 2,
   Clubs = 3,
   Spades = 4
};

// or...
enum class CardSuit {
   Diamonds = 1,
   Hearts = 2,
   Clubs = 3,
   Spades = 4
};

Eine C++-Enumerationsform in einem Klassendiagramm gleicht in Struktur und Funktionsweise einer Strukturform, sie trägt allerdings die Bezeichnung Enum oder Enumerationsklasse, sie ist nicht blau, sondern rosa und wird mit farbigem Rahmen an der linken und oberen Begrenzung angezeigt. Sowohl Enumerationsformen als auch Strukturformen sind eckig.

Weitere Informationen zur Verwendung des enum-Typs finden Sie unter Enumerationen.

C++-TypeDefs im Klassen-Designer

TypeDef-Anweisungen erstellen eine oder mehrere Dereferenzierungsebenen zwischen einem Namen und seinem zugrundeliegenden Typ. Der Klassen-Designer unterstützt z.B. folgende TypeDef-Typen für C++, die mithilfe des Schlüsselworts typedef deklariert werden:

typedef class coord
{
   void P(x,y);
   unsigned x;
   unsigned y;
} COORD;

Sie können diesen Typ dann zum Deklarieren einer Instanz verwenden:

COORD OriginPoint;

Klassen- und Strukturformen

Eine C++-Typdefinition weist im Klassen-Designer die Form des in der TypeDef definierten Typs auf. Wenn die Quelle typedef class deklariert, hat die Form abgerundete Ecken und trägt die Bezeichnung Class. Für typedef struct hat die Form rechtwinklige Ecken und die Bezeichnung Struct.

Klassen und Strukturen können geschachtelte deklarierte TypeDefs enthalten. Im Klassen-Designer können Klassen- und Strukturformen nun geschachtelte TypeDef-Deklarationen als geschachtelte Formen anzeigen.

Typedef-Formen unterstützen die Befehle Als Zuordnung anzeigen und Als Sammlungszuordnung anzeigen im Kontextmenü.

Beispiel für eine Klassentypdefinition

class B {};
typedef B MyB;

C++ class typedef in Class Designer

Beispiel für eine Strukturtypdefinition

typedef struct mystructtag
{
    int   i;
    double f;
} mystruct;

C++ struct typedef in Class Designer

Unbenannte TypeDefs

Zwar können Sie eine TypeDef ohne Namen deklarieren, der Klassen-Designer verwendet aber nicht den Namen des Tags, den Sie angeben. Der Klassen-Designer verwendet den Namen, der von der Klassenansicht generiert wird. Beispielsweise ist folgende Deklaration gültig, wird aber in der Klassenansicht und im Klassen-Designer als ein Objekt namens __unnamed angezeigt:

typedef class coord
{
   void P(x,y);
   unsigned x;
   unsigned y;
};

Hinweis

Der Klassen-Designer zeigt eine TypeDef nicht an, wenn deren Quelltyp ein Funktionszeiger ist.

Informationen zu Einschränkungen für C++-Codeelemente

  • Wenn ein C++-Projekt geladen ist, befindet sich der Klassen-Designer in einem schreibgeschützten Modus. Sie können das Klassendiagramm ändern, aber keine Änderungen am Klassendiagramm im Quellcode speichern.

  • Der Klassen-Designer unterstützt nur die native C++-Semantik. Bei C++-Projekten, die in verwalteten Code kompiliert werden, visualisiert der Klassen-Designer nur Codeelemente, bei denen es sich um native Typen handelt. Daher können Sie zwar ein Klassendiagramm zu einem Projekt hinzufügen, aber der Klassen-Designer visualisiert keine Elemente, in denen die IsManaged-Eigenschaft auf true festgelegt ist (d.h. Werttypen und Referenztypen).

  • Bei C++-Projekten liest der Klassen-Designer nur die Definition des Typs. Nehmen wir beispielsweise an, dass Sie einen Typ in einer Headerdatei (. h) und dessen Member in einer Implementierungsdatei (.cpp) definieren. Wenn Sie „Klassendiagramm anzeigen“ für die Implementierungsdatei (.cpp) aufrufen, zeigt der Klassen-Designer nichts an. Ein weiteres Beispiel: Wenn Sie „Klassendiagramm anzeigen“ für eine CPP-Datei aufrufen, die eine #include-Anweisung zum Einschließen anderer Dateien verwendet, aber keine eigentlichen Klassendefinitionen enthält, zeigt der Klassen-Designer erneut nichts an.

  • IDL-Dateien (.idl), die COM-Schnittstellen und Typbibliotheken definieren, werden in Diagrammen nicht angezeigt, sofern sie nicht in systemeigenen C++-Code kompiliert werden.

  • Der Klassen-Designer unterstützt keine globale Funktionen und Variablen.

  • Der Klassen-Designer unterstützt keine Unions. Dies ist eine besondere Art von Klasse, bei der der zugeordnete Arbeitsspeicher nur so groß wie der größte Datenmember der Union ist.

  • Der Klassen-Designer zeigt keine grundlegenden Datentypen wie int und char an.

  • Der Klassen-Designer zeigt keine Typen an, die außerhalb des aktuellen Projekts definiert sind, wenn das Projekt keinen richtigen Verweise auf diese Typen besitzt.

  • Der Klassen-Designer kann geschachtelte Typen anzeigen, jedoch keine Beziehungen zwischen einem geschachtelten Typ und anderen Typen.

  • Der Klassen-Designer kann keine Typen anzeigen, die „void“ sind oder von einem void-Typ abgeleitet sind.

Behandlung von Anzeigeproblemen und Problemen bei der Typauflösung

Speicherort der Quelldateien

Der Klassen-Designer merkt sich den Speicherort der Quelldateien nicht. Wenn Sie die Projektstruktur ändern oder Quelldateien im Projekt verschieben, kann der Klassen-Designer daher den Typ verlieren (insbesondere den Quelltyp einer TypeDef, von Basisklassen oder von Zuordnungstypen). Es wird möglicherweise ein Fehler angezeigt, z.B. Dieser Typ kann im Klassen-Designer nicht angezeigt werden. In diesem Fall ziehen Sie den geänderten oder verschobenen Quellcode in das Klassendiagramm, um ihn erneut anzuzeigen.

Update- und Leistungsprobleme

Bei C++-Projekten kann es zwischen 30 und 60 Sekunden dauern, bis eine Änderung in der Quelldatei im Klassendiagramm angezeigt wird. Diese Verzögerung kann auch dazu führen, dass der Klassen-Designer den Fehler In der Auswahl wurden keine Typen gefunden auslöst. Wenn Sie einen solchen Fehler erhalten, klicken Sie in der Fehlermeldung auf Abbrechen, und warten Sie darauf, dass das Codeelement in der Klassenansicht angezeigt wird. Danach sollte der Klassen-Designer den Typ anzeigen können.

Wenn ein Klassendiagramm nicht mit den Änderungen aktualisiert wird, die Sie im Code vorgenommen haben, müssen Sie möglicherweise das Diagramm schließen und erneut öffnen.

Probleme bei der Typauflösung

Der Klassen-Designer kann Typen aus folgenden Gründen möglicherweise nicht auflösen:

  • Der Typ ist in einem Projekt oder einer Assembly, auf das/die nicht aus dem Projekt mit dem Klassendiagramm verwiesen wird. Um diesen Fehler zu beheben, fügen Sie einen Verweis auf das Projekt oder die Assembly mit dem Typ hinzu. Weitere Informationen finden Sie unter Verwalten von Verweisen in einem Projekt.

  • Der Typ befindet sich nicht im richtigen Bereich, sodass der Klassen-Designer ihn nicht finden kann. Stellen Sie sicher, dass dem Code nicht eine Anweisung using, imports, oder #include fehlt. Stellen Sie außerdem sicher, dass Sie den Typ (oder einen zugehörigen Typ) nicht aus dem Namespace verschoben haben, in dem er sich ursprünglich befand.

  • Der Typ ist nicht vorhanden (oder wurde auskommentiert). Stellen Sie zum Beheben dieses Fehlers sicher, dass Sie den Typ nicht gelöscht oder auskommentiert haben.

  • Der Typ befindet sich in einer Bibliothek, auf die mit einer #import-Direktive verwiesen wird. Eine mögliche Problemumgehung besteht darin, den generierten Code (die TLH-Datei) manuell zu einer #include-Anweisung in der Headerdatei hinzufügen.

  • Stellen Sie sicher, dass der Klassen-Designer den von Ihnen eingegebenen Typ unterstützt. Siehe Einschränkungen für C++-Codeelemente.

Der Fehler, der am ehesten für eine Typauflösung angezeigt wird, ist Für mindestens eine Form im Klassendiagramm „<Element>“ wurde kein Code gefunden. Diese Fehlermeldung besagt nicht notwendigerweise, dass der Code fehlerhaft ist. Es gibt nur an, dass Klassen-Designer den Code nicht anzeigen kann. Versuchen Sie folgende Maßnahmen:

  • Stellen Sie sicher, dass der Typ vorhanden ist. Stellen Sie sicher, dass Sie den Quellcode nicht versehentlich auskommentiert oder gelöscht haben.

  • Versuchen Sie, den Typ aufzulösen. Der Typ befindet sich möglicherweise in einem Projekt oder einer Assembly, auf das/die nicht aus dem Projekt mit dem Klassendiagramm verwiesen wird. Um diesen Fehler zu beheben, fügen Sie einen Verweis auf das Projekt oder die Assembly mit dem Typ hinzu. Weitere Informationen finden Sie unter Verwalten von Verweisen in einem Projekt.

  • Stellen Sie sicher, dass sich der Typ im richtigen Bereich befindet, sodass Klassen-Designer ihn finden kann. Stellen Sie sicher, dass dem Code nicht eine Anweisung using, imports, oder #include fehlt. Stellen Sie außerdem sicher, dass Sie den Typ (oder einen zugehörigen Typ) nicht aus dem Namespace verschoben haben, in dem er sich ursprünglich befand.

Tipp

Weitere Informationen zur Problembehandlung finden Sie unter Fehler beim Klasse-Designer.