Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Projektant klas 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.
Projektant klas 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
Struktur
Enum
Makro (wyświetla widok po przetworzeniu makra)
Typedef
Uwaga / Notatka
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 Projektancie klas
Projektant klas 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 / Notatka
Projektant klas nie obsługuje unii (specjalnym typem klasy, w którym przydzielona pamięć jest tylko ilością niezbędną dla największego elementu danych).
Proste dziedziczenie
Kiedy przeciągasz więcej niż jedną klasę na diagram klas, a klasy mają relację dziedziczenia, łączy je strzałka. 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
Projektant klas 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 na 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 / Notatka
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 wielokrotnego, zobacz Dziedziczenie wielokrotne i Wiele klas bazowych.
Klasy abstrakcyjne
Projektant klas 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 na przykładzie "Wielo dziedziczenia" wcześniej w tym dokumencie, możesz utworzyć obiekty klasy Bird indywidualnie w następujący sposób:
int main()
{
Bird sparrow;
Bird crow;
Bird eagle;
}
Może nie mieć zamiaru tworzyć instancji klasy Swimmer jako pojedynczych obiektów. Możesz zamierzać jedynie wyprowadzać z niej 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 pochodna z abstrakcyjnej klasy bazowej musi zastąpić każdą funkcję czysto wirtualną w tej klasie bazowej lub klasa pochodna nie może zostać zinstanializowana. 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, Class Designer rysuje linię dziedziczenia od Fish do Swimmer.
Klasy anonimowe
Projektant klas 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. Projektant klas wyświetla anonimowe klasy i struktury w taki sam sposób jak odpowiednie typy. Mimo że można zadeklarować i wyświetlić anonimowe klasy i struktury, Projektant klas 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 Projektancie klas jako element o nazwie __unnamed.
Aby uzyskać więcej informacji na temat klas anonimowych, zobacz Anonimowe typy klas.
Klasy szablonów
Projektant klas obsługuje wizualizację klas szablonów. Deklaracje zagnieżdżone są obsługiwane. W poniższej tabeli przedstawiono niektóre typowe deklaracje.
| Element kodu | Widok Projektanta 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 Projektanta 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 Projektanta 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 BClass (wskazuje na klasę A) CClass (wskazuje na klasę A) |
W poniższej tabeli przedstawiono kilka przykładów funkcji szablonu częściowej specjalizacji.
| Element kodu | Widok Projektanta klas |
|---|---|
class A{template <class T, class U>void func(T a, U b);template <class T>void func(T a, int b);}; |
Afunc<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> {}; |
AClass -> C<int> C<T>Klasa szablonu |
W poniższej tabeli przedstawiono kilka przykładów dziedziczenia szablonu.
| Element kodu | Widok Projektanta klas |
|---|---|
template <class T>class C {};template<>class C<int> {class B {};}class A : C<int>::B {}; |
AClass ->B C<int>Class (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 klas.
| Element kodu | Widok Projektanta klas |
|---|---|
template <class T>class C {};template<>class C<int> {};class A : C<int> {};class D : C<float> {}; |
AClass ->C<int> C<int>Class C<T>Klasa szablonu DClass ->C<float> |
class B {template <class T>T min (const T &a, const T &b);}; |
Bmin <T> |
Wyliczenia języka C++ w Projektancie klas
Projektant klas obsługuje typy C++ enum i typy z zakresem enum class. 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 w języku C++ na diagramie klasy wygląda i działa jak kształt struktury, z tą różnicą, że ma napis Enum lub Enum class, ma różowy kolor zamiast niebieskiego i posiada 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 Projektancie klas
Instrukcje Typedef tworzą co najmniej jedną warstwę pośrednią między nazwą a jego typem bazowym.
Projektant klas 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 Projektancie klas definicja typu C++ ma kształt typu określonego 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, kształt ma kwadratowe narożniki i etykietę Struct.
Klasy i struktury mogą mieć zagnieżdżone definicje typów zadeklarowane w nich. W Projektancie klas kształty klas i struktur mogą przedstawiać 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, Projektant klas nie używa określonej nazwy tagu. Projektant klas używa nazwy generowanej przez widok klas . Na przykład następująca deklaracja jest prawidłowa, ale jest wyświetlana w widoku klas i Projektancie klas jako obiekt o nazwie __unnamed:
typedef class coord
{
void P(x,y);
unsigned x;
unsigned y;
};
Uwaga / Notatka
Projektant klas 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++ projektant klas 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.
Projektant klas obsługuje tylko natywną semantykę C++. W przypadku projektów C++, które są kompilowane w kodzie zarządzanym, Projektant klas wizualizuje tylko elementy kodu, które są typami natywnymi. W związku z tym można dodać diagram klas do projektu, ale Projektant klas nie umożliwia wizualizacji elementów, w których właściwość
IsManagedjest ustawiona natrue(czyli na typy wartości i typy referencyjne).W przypadku projektów języka C++ Projektant klas 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 "Wyświetl diagram klas" w pliku implementacji (.cpp), projektant klas nie wyświetli niczego. W innym przykładzie, jeśli wywołasz "View Class Diagram" (Wyświetl diagram klas) w pliku .cpp, który używa
#includeinstrukcji w celu uwzględnienia innych plików, ale nie zawiera żadnych rzeczywistych definicji klas, projektant klas ponownie nie wyświetla niczego.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++.
Projektant klas nie obsługuje funkcji globalnych i zmiennych.
Projektant klas nie obsługuje związków. Jest to specjalny typ klasy, w której przydzielona pamięć jest tylko ilością niezbędną dla największej składowej danych unii.
Projektant klas nie wyświetla podstawowych typów danych, takich jak
intichar.Projektant klas nie wyświetla typów zdefiniowanych poza bieżącym projektem, jeśli projekt nie ma poprawnych odwołań do tych typów.
Projektant klas może wyświetlać typy zagnieżdżone, ale nie relacje między typem zagnieżdżonym a innymi typami.
Projektant klas nie może wyświetlać typów, które są puste lub pochodzą z typu void.
Rozwiązywanie problemów z rozpoznawaniem typów i wyświetlaniem
Lokalizacja plików źródłowych
Projektant klas nie śledzi lokalizacji plików źródłowych. W związku z tym, jeśli zmodyfikujesz strukturę projektu lub przeniesiesz pliki źródłowe w projekcie, Projektant klas 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 Projektant klas nie może wyświetlić tego typu elementu. 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 projektant klas 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 projektant klas powinien mieć możliwość wyświetlenia typu.
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
Projektant klas 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, więc projektant klas nie może go zlokalizować. Upewnij się, że w kodzie nie brakuje instrukcji
using,importslub#include. Upewnij się również, że typ (lub powiązany typ) nie został przeniesiony z przestrzeni nazw, w której pierwotnie znajdował się.Rodzaj 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órej odwołuje się dyrektywa #import. Możliwe obejście polega na ręcznym dodaniu wygenerowanego kodu (pliku tlh) w dyrektywie #include w pliku nagłówka.
Upewnij się, że projektant klas 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 mógł wyświetlić twojego kodu. Wypróbuj następujące miary:
Upewnij się, że typ istnieje. Upewnij się, że nie skomentowano lub usunięto kodu źródłowego przez pomyłkę.
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 klas mógł go zlokalizować. Upewnij się, że w kodzie nie brakuje instrukcji
using,importslub#include. Upewnij się również, że typ (lub powiązany typ) nie został przeniesiony z przestrzeni nazw, w której pierwotnie znajdował się.
Wskazówka
Aby uzyskać dodatkowe informacje dotyczące rozwiązywania problemów, zobacz Błędy projektanta klas.