Praca z kodem C++ w Projektant klasy
Klasa Projektant wyświetla wizualną powierzchnię projektową o nazwie diagram klas, który zapewnia wizualną reprezentację elementów kodu w projekcie. Diagramy klas umożliwiają projektowanie i wizualizowanie klas i innych typów w projekcie.
Klasa Projektant obsługuje następujące elementy kodu C++:
Klasa (przypomina kształt klasy zarządzanej, z tą różnicą, że może mieć wiele relacji dziedziczenia)
Klasa anonimowa (wyświetla wygenerowaną nazwę widoku klas dla typu anonimowego)
Klasa szablonu
Struct
Wyliczenie
Makro (wyświetla widok po przetworzeniu makra)
Typedef
Uwaga
Nie jest to samo co diagram klas UML, który można utworzyć w projekcie modelowania. Aby uzyskać więcej informacji, zobacz Diagramy klas UML: dokumentacja.
Klasy języka C++ w Projektant klas
Klasa Projektant obsługuje klasy języka C++ i wizualizuje natywne klasy języka C++ w taki sam sposób jak kształty klas Visual Basic i C#, z tą różnicą, że klasy języka C++ mogą mieć wiele relacji dziedziczenia. Możesz rozwinąć kształt klasy, aby wyświetlić więcej pól i metod w klasie lub zwinąć go w celu zaoszczędzenia miejsca.
Uwaga
Klasa Projektant nie obsługuje związków (specjalny typ klasy, w której przydzielona pamięć jest tylko ilością niezbędną dla największego elementu członkowskiego danych unii).
Proste dziedziczenie
Przeciągając więcej niż jedną klasę na diagram klas, a klasy mają relację dziedziczenia klas, strzałka łączy je. Strzałka wskazuje kierunek klasy bazowej. Jeśli na przykład następujące klasy są wyświetlane na diagramie klasy, strzałka je łączy, wskazując od B do A:
class A {};
class B : A {};
Możesz również przeciągnąć tylko klasę B do diagramu klas, kliknąć prawym przyciskiem myszy kształt klasy dla klasy B, a następnie kliknąć polecenie Pokaż klasy bazowe. Spowoduje to wyświetlenie jej klasy bazowej: A.
Wiele dziedziczenia
Klasa Projektant obsługuje wizualizację relacji dziedziczenia wielu klas. Wielokrotne dziedziczenie jest używane, gdy klasa pochodna ma atrybuty więcej niż jednej klasy bazowej. Oto przykład wielokrotnego dziedziczenia:
class Bird {};
class Swimmer {};
class Penguin : public Bird, public Swimmer {};
Przeciągając więcej niż jedną klasę na diagram klas, a klasy mają relację dziedziczenia wielu klas, strzałka łączy je. Strzałka wskazuje kierunek klas bazowych.
Kliknięcie prawym przyciskiem myszy kształtu klasy, a następnie kliknięcie pozycji Pokaż klasy bazowe powoduje wyświetlenie klas bazowych dla wybranej klasy.
Uwaga
Polecenie Pokaż klasy pochodne nie jest obsługiwane dla kodu C++. Klasy pochodne można wyświetlić, przechodząc do widoku klas, rozwijając węzeł typu, rozwijając podfolder Typy pochodne, a następnie przeciągając te typy na diagram klasy.
Aby uzyskać więcej informacji na temat dziedziczenia wielu klas, zobacz Wiele dziedziczenia i wielu klas bazowych.
Klasy abstrakcyjne
Klasa Projektant obsługuje klasy abstrakcyjne (nazywane również "abstrakcyjne klasy bazowe"). Są to klasy, których nigdy nie tworzy się, ale z których można tworzyć inne klasy. Korzystając z przykładu z "Wiele dziedziczenia" wcześniej w tym dokumencie, możesz utworzyć wystąpienie Bird
klasy jako pojedynczych obiektów w następujący sposób:
int main()
{
Bird sparrow;
Bird crow;
Bird eagle;
}
Jednak nie zamierzasz utworzyć wystąpienia Swimmer
klasy jako pojedynczych obiektów. Można utworzyć tylko inne typy klas zwierząt, na przykład Penguin
, Whale
i Fish
. W takim przypadku należy zadeklarować klasę Swimmer
jako abstrakcyjną klasę bazową.
Aby zadeklarować klasę jako abstrakcyjną, możesz użyć słowa kluczowego abstract
. Składowe oznaczone jako abstrakcyjne lub uwzględnione w klasie abstrakcyjnej są wirtualne i muszą być implementowane przez klasy pochodzące z klasy abstrakcyjnej.
class Swimmer abstract
{
virtual void swim();
void dive();
};
Klasę można również zadeklarować jako abstrakcyjną, dołączając co najmniej jedną czystą funkcję wirtualną:
class Swimmer
{
virtual void swim() = 0;
void dive();
};
Po wyświetleniu tych deklaracji na diagramie klas nazwa Swimmer
klasy i jej czysta funkcja swim
wirtualna są wyświetlane w kursywie w kształcie klasy abstrakcyjnej wraz z notacją Abstrakcyjna klasa. Zwróć uwagę, że kształt typu klasy abstrakcyjnej jest taki sam jak kształt klasy regularnej, z tą różnicą, że jej obramowanie jest linią kropkowaną.
Klasa pochodząca z abstrakcyjnej klasy bazowej musi zastąpić każdą czystą funkcję wirtualną w klasie bazowej lub nie można utworzyć wystąpienia klasy pochodnej. Na przykład jeśli utworzysz klasę Fish
z Swimmer
klasy , Fish
należy zastąpić metodę swim
:
class Fish : public Swimmer
{
void swim(int speed);
};
int main()
{
Fish guppy;
}
Po wyświetleniu tego kodu na diagramie klas klasa Projektant rysuje wiersz dziedziczenia z Fish
do Swimmer
.
Klasy anonimowe
Klasa Projektant obsługuje klasy anonimowe. Anonimowe typy klas to klasy zadeklarowane bez identyfikatora. Nie mogą mieć konstruktora ani destruktora, nie mogą być przekazywane jako argumenty do funkcji i nie mogą być zwracane jako wartości zwracane z funkcji. Możesz użyć klasy anonimowej, aby zastąpić nazwę klasy nazwą typedef, jak w poniższym przykładzie:
typedef struct
{
unsigned x;
unsigned y;
} POINT;
Struktury mogą być również anonimowe. Klasa Projektant wyświetla anonimowe klasy i struktury tak samo, jak w przypadku wyświetlania odpowiedniego typu. Mimo że można zadeklarować i wyświetlić anonimowe klasy i struktury, klasa Projektant nie będzie używać określonej nazwy tagu. Będzie ona używać nazwy generowanej przez widok klas. Klasa lub struktura jest wyświetlana w widoku klas i Projektant jako element o nazwie __unnamed.
Aby uzyskać więcej informacji na temat klas anonimowych, zobacz Anonimowe typy klas.
Klasy szablonów
Klasa Projektant obsługuje wizualizację klas szablonów. Obsługiwane są deklaracje zagnieżdżone. W poniższej tabeli przedstawiono niektóre typowe deklaracje.
Element kodu | Widok Projektant klas |
---|---|
template <class T> class A {}; |
A<T> Klasa szablonu |
template <class T, class U> class A {}; |
A<T, U> Klasa szablonu |
template <class T, int i> class A {}; |
A<T, i> Klasa szablonu |
template <class T, template <class K> class U> class A {}; |
A<T, U> Klasa szablonu |
W poniższej tabeli przedstawiono kilka przykładów częściowej specjalizacji.
Element kodu | Widok Projektant klas |
---|---|
template<class T, class U> class A {}; |
A<T, U> Klasa szablonu |
template<class T> class A<T, T> {}; |
A<T, T> Klasa szablonu |
template <class T> class A<T, int> {}; |
A<T, int> Klasa szablonu |
template <class T1, class T2> class A<T1*, T2*> {}; |
A<T1*, T2*> Klasa szablonu |
W poniższej tabeli przedstawiono kilka przykładów dziedziczenia w częściowej specjalizacji.
Element kodu | Widok Projektant klas |
---|---|
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> Klasa szablonu B Klasa (wskazuje na klasę A) C Klasa (wskazuje na klasę A) |
W poniższej tabeli przedstawiono kilka przykładów funkcji szablonu częściowej specjalizacji.
Element kodu | Widok Projektant klas |
---|---|
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 przeciążenie) |
template <class T1> class A { template <class T2> class B {}; }; template<> template<> class A<type>::B<type> {}; |
A<T1> Klasa szablonu B<T2> Klasa szablonu (B jest zawarty w klasie A w obszarze Typy zagnieżdżone) |
template <class T> class C {}; class A : C<int> {}; |
A Klasa -> C<int> C<T> Klasa szablonu |
W poniższej tabeli przedstawiono kilka przykładów dziedziczenia szablonu.
Element kodu | Widok Projektant klas |
---|---|
template <class T> class C {}; template<> class C<int> { class B {}; } class A : C<int>::B {}; |
A Klasa ->B C<int> Klasa (B jest zawarty w klasie C w obszarze Typy zagnieżdżone) C<T> Klasa szablonu |
W poniższej tabeli przedstawiono kilka przykładów kanonicznego wyspecjalizowanego połączenia klasy.
Element kodu | Widok Projektant klas |
---|---|
template <class T> class C {}; template<> class C<int> {}; class A : C<int> {}; class D : C<float> {}; |
A Klasa ->C<int> C<int> Klasa C<T> Klasa szablonu D Klasa ->C<float> |
class B { template <class T> T min (const T &a, const T &b); }; |
B min <T> |
Wyliczenia języka C++ w Projektant klas
Klasa Projektant obsługuje typy C++ enum
i o określonym enum class
zakresie. Oto przykład:
enum CardSuit {
Diamonds = 1,
Hearts = 2,
Clubs = 3,
Spades = 4
};
// or...
enum class CardSuit {
Diamonds = 1,
Hearts = 2,
Clubs = 3,
Spades = 4
};
Kształt wyliczenia języka C++ na diagramie klasy wygląda i działa jak kształt struktury, z tą różnicą, że etykieta odczytuje klasę wyliczenia lub wyliczenia, jest różowa zamiast niebieska i ma kolorowe obramowanie na lewym i górnym marginesie. Oba kształty wyliczania i kształty struktury mają kwadratowe narożniki.
Aby uzyskać więcej informacji na temat używania enum
typu, zobacz Wyliczenia.
Definicje typów języka C++ w Projektant klasy
Instrukcje Typedef tworzą co najmniej jedną warstwę pośrednią między nazwą a jego typem bazowym. Klasa Projektant obsługuje typy typedef języka C++, które są deklarowane za pomocą słowa kluczowego typedef
, na przykład:
typedef class coord
{
void P(x,y);
unsigned x;
unsigned y;
} COORD;
Następnie możesz użyć tego typu, aby zadeklarować wystąpienie:
COORD OriginPoint;
Kształty klas i struktur
W Projektant klasy definicja typu C++ ma kształt typu określony w definicji typów. Jeśli źródło deklaruje typedef class
, kształt ma zaokrąglone rogi i etykietę Klasa. W przypadku typedef struct
elementu kształt ma kwadratowe narożniki i etykietę Struktura.
Klasy i struktury mogą mieć zagnieżdżone definicje typów zadeklarowane w nich. W Projektant klasy kształty klasy i struktury mogą wyświetlać zagnieżdżone deklaracje typedef jako zagnieżdżone kształty.
Kształty Typedef obsługują polecenia Pokaż jako skojarzenie i Pokaż jako skojarzenie kolekcji w menu prawym przyciskiem myszy (menu kontekstowe).
Przykład klasy typedef
class B {};
typedef B MyB;
Przykład definicji typu struktury
typedef struct mystructtag
{
int i;
double f;
} mystruct;
Nienazwane definicje typów
Mimo że można zadeklarować definicję typu bez nazwy, klasa Projektant nie używa określonej nazwy tagu. Klasa Projektant używa nazwy generowanej przez widok klasy. Na przykład następująca deklaracja jest prawidłowa, ale jest wyświetlana w widoku klas i Projektant klasy jako obiekt o nazwie __unnamed:
typedef class coord
{
void P(x,y);
unsigned x;
unsigned y;
};
Uwaga
Klasa Projektant nie wyświetla definicji typów, których typem źródłowym jest wskaźnik funkcji.
Dowiedz się więcej o ograniczeniach dotyczących elementów kodu w języku C++
Po załadowaniu projektu języka C++ klasa Projektant działa w sposób tylko do odczytu. Diagram klas można zmienić, ale nie można zapisać zmian z diagramu klas z powrotem do kodu źródłowego.
Klasa Projektant obsługuje tylko natywną semantyka języka C++. W przypadku projektów C++ skompilowanych w kodzie zarządzanym klasa Projektant wizualizuje tylko elementy kodu, które są typami natywnymi. W związku z tym można dodać diagram klas do projektu, ale klasa Projektant nie umożliwi wizualizacji elementów, w których
IsManaged
właściwość jest ustawionatrue
na (czyli typy wartości i typy referencyjne).W przypadku projektów języka C++ klasa Projektant odczytuje tylko definicję typu. Załóżmy na przykład, że definiujesz typ w pliku nagłówka (h) i definiujesz jego elementy członkowskie w pliku implementacji (cpp). Jeśli wywołasz plik "View Class Diagram" (Wyświetl diagram klas) w pliku implementacji (cpp), klasa Projektant nie wyświetla niczego. W innym przykładzie, jeśli wywołasz "View Class Diagram" w pliku cpp, który używa
#include
instrukcji do uwzględnienia innych plików, ale nie zawiera żadnych rzeczywistych definicji klas, klasa Projektant ponownie nie wyświetla nic.Pliki IDL (idl), które definiują interfejsy COM i biblioteki typów, nie są wyświetlane na diagramach, chyba że są kompilowane do natywnego kodu C++.
Klasa Projektant nie obsługuje funkcji globalnych i zmiennych.
Projektant klasy nie obsługuje związków zawodowych. Jest to specjalny typ klasy, w której przydzielona pamięć jest tylko ilością niezbędną dla największej składowej danych unii.
Klasa Projektant nie wyświetla podstawowych typów danych, takich jak
int
ichar
.Klasa Projektant nie wyświetla typów zdefiniowanych poza bieżącym projektem, jeśli projekt nie ma poprawnych odwołań do tych typów.
Klasa Projektant może wyświetlać typy zagnieżdżone, ale nie relacje między typem zagnieżdżonym a innymi typami.
Klasa Projektant nie może wyświetlać typów, które są puste lub pochodzą z typu pustki.
Rozwiązywanie problemów z rozpoznawaniem typów i wyświetlaniem
Lokalizacja plików źródłowych
Projektant klasy nie śledzi lokalizacji plików źródłowych. W związku z tym w przypadku modyfikowania struktury projektu lub przenoszenia plików źródłowych w projekcie klasa Projektant może utracić śledzenie typu (zwłaszcza typu źródłowego typu typedef, klas bazowych lub typów skojarzeń). Może zostać wyświetlony błąd, taki jak Klasa Projektant nie może wyświetlić tego typu. Jeśli tak, przeciągnij zmodyfikowany lub przeniesiony kod źródłowy do diagramu klas ponownie, aby go ponownie odtworzyć.
Problemy z aktualizacją i wydajnością
W przypadku projektów języka C++ może upłynąć od 30 do 60 sekund, aby zmiana pliku źródłowego pojawiła się na diagramie klasy. To opóźnienie może również spowodować, że klasa Projektant zgłosić błąd Nie znaleziono typów w zaznaczeniu. Jeśli wystąpi błąd, taki jak ten, kliknij przycisk Anuluj w komunikacie o błędzie i poczekaj, aż element kodu pojawi się w widoku klasy. Po wykonaniu tej czynności klasa Projektant powinna być w stanie wyświetlić typ.
Jeśli diagram klas nie zostanie zaktualizowany o zmiany wprowadzone w kodzie, może być konieczne zamknięcie diagramu i otwarcie go ponownie.
Problemy z rozwiązywaniem typów
Klasa Projektant może nie być w stanie rozpoznać typów z następujących powodów:
Typ znajduje się w projekcie lub zestawie, do którego nie odwołuje się projekt zawierający diagram klas. Aby naprawić ten błąd, dodaj odwołanie do projektu lub zestawu zawierającego typ. Aby uzyskać więcej informacji, zobacz Zarządzanie odwołaniami w projekcie.
Typ nie znajduje się w prawidłowym zakresie, dlatego nie można zlokalizować klasy Projektant. Upewnij się, że w kodzie nie brakuje instrukcji
using
,imports
lub#include
. Upewnij się również, że typ (lub powiązany typ) nie został przeniesiony z przestrzeni nazw, w której pierwotnie znajdował się.Typ nie istnieje (lub został skomentowany). Aby rozwiązać ten błąd, upewnij się, że typ nie został skomentowany lub usunięty.
Typ znajduje się w bibliotece, do których odwołuje się dyrektywa #import. Możliwe obejście polega na ręcznym dodaniu wygenerowanego kodu (pliku tlh) do dyrektywy #include do pliku nagłówka.
Upewnij się, że Projektant Klasy obsługuje wprowadzony typ. Zobacz Ograniczenia dotyczące elementów kodu języka C++.
Błąd, który najprawdopodobniej zobaczysz dla problemu z rozwiązaniem typu, to Nie można odnaleźć kodu dla co najmniej jednego kształtu na diagramie klasy "<element>". Ten komunikat o błędzie nie musi wskazywać, że kod jest w błędzie. Wskazuje tylko, że projektant klas nie może wyświetlić kodu. Wypróbuj następujące miary:
Upewnij się, że typ istnieje. Upewnij się, że nie oznaczono przypadkowo komentarza ani nie usunięto kodu źródłowego.
Spróbuj rozpoznać typ. Typ może znajdować się w projekcie lub zestawie, do którego nie odwołuje się projekt zawierający diagram klas. Aby naprawić ten błąd, dodaj odwołanie do projektu lub zestawu zawierającego typ. Aby uzyskać więcej informacji, zobacz Zarządzanie odwołaniami w projekcie.
Upewnij się, że typ znajduje się w prawidłowym zakresie, aby Projektant klasa mogła go zlokalizować. Upewnij się, że w kodzie nie brakuje instrukcji
using
,imports
lub#include
. Upewnij się również, że typ (lub powiązany typ) nie został przeniesiony z przestrzeni nazw, w której pierwotnie znajdował się.
Napiwek
Aby uzyskać dodatkowe informacje dotyczące rozwiązywania problemów, zobacz Błędy Projektant klasy.