Usare il codice C++ in Progettazione classi

Progettazione classi mostra un'area di progettazione visiva denominata diagramma classi che fornisce una rappresentazione visiva degli elementi di codice nel progetto. Si possono usare i diagrammi classi per progettare e visualizzare le classi e gli altri tipi in un progetto.

Progettazione classi supporta gli elementi di codice C++ seguenti:

  • Classe (simile a una forma di classe gestita, con la differenza che può avere relazioni di ereditarietà multiple)

  • Classe anonima (visualizza il nome generato da Visualizzazione classi per il tipo anonimo)

  • Classe modello

  • Struct

  • Enumerazione

  • Macro (visualizza la prospettiva post-elaborata della macro)

  • Typedef

Nota

Non corrisponde al diagramma classi UML, che è possibile creare in un progetto di modellazione. Per altre informazioni, vedere UML Class Diagrams: Reference (Diagrammi classi UML: riferimenti)

Classi C++ in Progettazione classi

Progettazione classi supporta le classi C++ e visualizza classi C++ native in modo analogo alle forme di classe di Visual Basic e C#, con la differenza che le classi C++ possono avere più relazioni di ereditarietà. È possibile espandere la forma classe in modo da visualizzare più campi e metodi nella classe o comprimerla per risparmiare spazio.

Nota

Progettazione classi non supporta le unioni, un tipo speciale di classe in cui la memoria allocata corrisponde solo alla quantità necessaria per il membro dati più grande dell'unione.

Ereditarietà semplice

Quando si trascina più di una classe su un diagramma classi, le classi che presentano una relazione di ereditarietà di classe sono connesse con una freccia che punta nella direzione della classe di base. Ad esempio, quando vengono visualizzate in un diagramma classi, le classi seguenti sono connesse con una freccia che parte da B e arriva ad A:

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

È anche possibile trascinare solo la classe B sul diagramma classi, fare clic col pulsante destro del mouse sulla forma classe relativa a B e quindi fare clic su Mostra classi base per visualizzare la relativa classe di base, ovvero A.

Ereditarietà multipla

Progettazione classi supporta la visualizzazione di relazioni di ereditarietà da classi multiple. L'ereditarietà multipla viene usata quando una classe derivata presenta attributi di più di una classe di base. Di seguito è riportato un esempio di ereditarietà multipla:

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

Quando si trascina più di una classe sul diagramma classi, le classi che presentano una relazione di ereditarietà da classi multiple sono connesse con una freccia che punta nella direzione delle classi di base.

Facendo clic con il pulsante destro del mouse su una forma classe e scegliendo Mostra classi base vengono visualizzate le classi di base per la classe selezionata.

Nota

Il comando Mostra classi derivate non è supportato per il codice C++. Per visualizzare le classi derivate, scegliere Visualizzazione classi, espandere il nodo dei tipi, espandere la sottocartella Tipi derivati e trascinare tali tipi sul diagramma classi.

Per altre informazioni sulle ereditarietà da classi multiple, vedere Ereditarietà multipla e Più classi base.

Classi astratte

Progettazione classi supporta le classi astratte, note anche come "classi di base astratte". Si tratta di classi per le quali non viene mai creata un'istanza, ma da cui è possibile derivare altre classi. Usando un esempio citato in "Ereditarietà multipla" più indietro in questo documento, è possibile creare un'istanza della classe Bird come singoli oggetti, come illustrato di seguito:

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

È però possibile che non si intenda creare un'istanza della classe Swimmer come singoli oggetti e che si intenda solo usarla per derivare altri tipi di classi di animali, ad esempio Penguin, Whale e Fish. In tal caso, è necessario dichiarare la classe Swimmer come classe di base astratta.

Per dichiarare una classe come astratta, si può usare la parola chiave abstract. I membri contrassegnati come astratti o inclusi in una classe astratta sono virtuali e devono essere implementati dalle classi che derivano dalla classe astratta.

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

È anche possibile dichiarare una classe come astratta includendo almeno una funzione virtuale pura:

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

Quando si visualizzano queste dichiarazioni in un diagramma classi, il nome della classe Swimmer e la relativa funzione virtuale pura swim vengono visualizzate in corsivo in una forma classe astratta, unitamente alla notazione Classe astratta. Si noti che la forma tipo di classe astratta è uguale a quella di una classe normale, ad eccezione del fatto che il bordo è costituito da una linea punteggiata.

Una classe derivata da una classe di base astratta deve eseguire l'override di ogni funzione virtuale pura della classe di base, altrimenti non è possibile creare un'istanza della classe derivata. Se, ad esempio, si deriva una classe Fish dalla classe Swimmer, Fish deve eseguire l'override del metodo swim:

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

int main()
{
   Fish guppy;
}

Quando si visualizza il codice in un diagramma classi, Progettazione classi traccia una linea di ereditarietà da Fish a Swimmer.

Classi anonime

Progettazione classi supporta le classi anonime. I tipi di classe anonimi sono classi dichiarate senza un identificatore. Non possono includere un costruttore o un distruttore, non possono essere passate come argomenti alle funzioni e non possono essere restituite come valori restituiti dalle funzioni. È possibile usare una classe anonima per sostituire un nome di classe con un nome typedef, come nell'esempio seguente:

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

Anche le strutture possono essere anonime. Progettazione classi visualizza classi e strutture anonime in modo analogo a come visualizza il rispettivo tipo. Anche se è possibile dichiarare e visualizzare classi e strutture anonime, Progettazione classi non usa il nome del tag specificato dall'utente, ma usa il nome generato da Visualizzazione classi. La classe o la struttura viene visualizzata in Visualizzazione classi e Progettazione classi come elemento denominato __unnamed.

Per altre informazioni sulle classi anonime, vedere Tipi di classe anonimi.

Classi modello

Progettazione classi supporta la visualizzazione di classi modello, nonché le dichiarazioni annidate. La tabella seguente illustra alcune dichiarazioni tipiche.

Elemento coda Visualizzazione di Progettazione classi
template <class T>

class A {};
A<T>

Classe modello
template <class T, class U>

class A {};
A<T, U>

Classe modello
template <class T, int i>

class A {};
A<T, i>

Classe modello
template <class T, template <class K> class U>

class A {};
A<T, U>

Classe modello

La tabella seguente illustra alcuni esempi di specializzazione parziale.

Elemento coda Visualizzazione di Progettazione classi
template<class T, class U>

class A {};
A<T, U>

Classe modello
template<class T>

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

Classe modello
template <class T>

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

Classe modello
template <class T1, class T2>

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

Classe modello

La tabella seguente illustra alcuni esempi di ereditarietà nella specializzazione parziale.

Elemento coda Visualizzazione di Progettazione classi
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>

Classe modello

B

Classe

(punta alla classe A)

C

Classe

(punta alla classe A)

La tabella seguente illustra alcuni esempi di funzioni del modello di specializzazione parziale.

Elemento coda Visualizzazione di Progettazione classi
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>

Classe modello

B<T2>

Classe modello

(B è contenuto all'interno della classe A in Tipi annidati)
template <class T>

class C {};

class A : C<int> {};
A

Classe

-> C<int>

C<T>

Classe modello

La tabella seguente illustra alcuni esempi di ereditarietà del modello.

Elemento coda Visualizzazione di Progettazione classi
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

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

Classe

->B

C<int>

Classe

(B è contenuto all'interno della classe C in Tipi annidati)

C<T>

Classe modello

La tabella seguente illustra alcuni esempi di tipica connessione di classe specializzata.

Elemento coda Visualizzazione di Progettazione classi
template <class T>

class C {};

template<>

class C<int> {};

class A : C<int> {};

class D : C<float> {};
A

Classe

->C<int>

C<int>

Classe

C<T>

Classe modello

D

Classe

->C<float>
class B {

template <class T>

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

};
B

min <T>

Enumerazioni C++ in Progettazione classi

Progettazione classi supporta i tipi enum e enum class con ambito in C++. Di seguito è illustrato un esempio:

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

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

Una forma di enumerazione C++ in un diagramma classi viene visualizzata e funziona come una forma di struttura, tranne per il fatto che l'etichetta Enum o Enum class è di colore rosa anziché blu e ha un bordo colorato sui margini sinistro e superiore. Entrambe le forme di enumerazione e struttura hanno angoli quadrati.

Per altre informazioni sull'uso del tipo enum, vedere Enumerazioni.

Typedef C++ in Progettazione classi

Le istruzioni typedef creano uno o più livelli di riferimento indiretto tra un nome e il relativo tipo sottostante. Progettazione classi supporta i tipi typedef di C++, che vengono dichiarati con la parola chiave typedef, ad esempio:

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

È quindi possibile usare questo tipo per dichiarare un'istanza:

COORD OriginPoint;

Forme di classi e struct

In Progettazione classi un typedef di C++ ha la forma del tipo specificato nel typedef. Se l'origine dichiara typedef class, la forma ha gli angoli arrotondati e l'etichetta Class. Per typedef struct la forma ha gli angoli quadrati e l'etichetta Struct.

Classi e strutture possono avere typedef dichiarati annidati all'interno di essi. In Progettazione classi le forme di classi e strutture possono visualizzare le dichiarazioni typedef annidate come forme annidate.

Le forme typedef supportano i comandi Mostra come associazione e Mostra come associazione di raccolte nel menu di scelta rapida.

Esempio di typedef di classe

class B {};
typedef B MyB;

C++ class typedef in Class Designer

Esempio di typedef di struct

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

C++ struct typedef in Class Designer

Typedef senza nome

Sebbene sia possibile dichiarare un typedef senza nome, Progettazione classi non usa il nome del tag specificato. Progettazione classi usa il nome generato da Visualizzazione classi. Ad esempio, la dichiarazione seguente è valida, ma appare in Visualizzazione classi e Progettazione classi come un oggetto denominato __unnamed:

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

Nota

Progettazione classi non visualizza i typedef il cui tipo di origine è un puntatore a funzione.

Informazioni sulle limitazioni per gli elementi di codice C++

  • Quando viene caricato un progetto C++, Progettazione classi funziona in modo di sola lettura. È possibile modificare il diagramma classi, ma non salvare modifiche dal diagramma classi nel codice sorgente.

  • Progettazione classi supporta solo semantica C++ nativa. Per i progetti C++ compilati in codice gestito, Progettazione classi visualizzerà solo gli elementi di codice che sono tipi nativi. Di conseguenza, è possibile aggiungere un diagramma classi a un progetto, ma Progettazione classi non consentirà di visualizzare elementi in cui la proprietà IsManaged è impostata su true (ovvero tipi di valore e tipi di riferimento).

  • Per i progetti C++, Progettazione classi legge solo la definizione del tipo. Ad esempio, si supponga di definire un tipo in un file di intestazione (.h) e i relativi membri in un file di implementazione (.cpp). Se si richiama "Visualizza diagramma classi" sul file di implementazione (.cpp), Progettazione classi non visualizzerà niente. Per fare un altro esempio, se si richiama "Visualizza diagramma classi" su un file .cpp che usa un'istruzione #include per includere altri file ma non contiene definizioni della classe, Progettazione classi analogamente non visualizzerà niente.

  • I file IDL (.idl), che definiscono le interfacce COM e le librerie dei tipi, non vengono visualizzati nei diagrammi a meno che non siano compilati in codice C++ nativo.

  • Progettazione classi non supporta funzioni e variabili globali.

  • Progettazione classi non supporta unioni. Si tratta di un tipo speciale di classe in cui la memoria allocata è solo la quantità necessaria per il membro dati più grande dell'unione.

  • Progettazione classi non visualizza tipi di dati di base come ad esempio int e char.

  • Progettazione classi non visualizza tipi definiti all'esterno del progetto corrente se il progetto non ha riferimenti corretti a tali tipi.

  • Progettazione classi visualizza i tipi annidati, ma non le relazioni tra un tipo annidato e altri tipi.

  • Progettazione classi non può visualizzare tipi void o che derivano da un tipo void.

Risoluzione dei problemi relativi al tipo e alla visualizzazione

Percorso dei file di origine

Progettazione classi non tiene traccia del percorso dei file di origine. Di conseguenza, se si modifica la struttura del progetto o si spostano file di origine nel progetto, Progettazione classi può perdere traccia del tipo (soprattutto il tipo di origine di un typedef, classi base o tipi di associazione). Si potrebbe ricevere un errore, ad esempio Progettazione classi: impossibile visualizzare il tipo. In tal caso, trascinare di nuovo il codice sorgente modificato o riposizionato nel diagramma classi per visualizzarlo nuovamente.

Problemi di aggiornamento e di prestazioni

Per i progetti C++, potrebbero essere necessari da 30 a 60 secondi per visualizzare una modifica nel file di origine nel diagramma classi. A causa di questo ritardo, Progettazione classi potrebbe anche generare l'errore Nessun tipo trovato nella selezione. Se viene visualizzato un messaggio di errore di questo tipo, scegliere Annulla nel messaggio di errore e attendere che l'elemento di codice venga visualizzato in Visualizzazione classi. A questo punto, Progettazione classi dovrebbe essere in grado di visualizzare il tipo.

Se il diagramma classi non viene aggiornato con le modifiche apportate nel codice, può essere necessario chiuderlo e riaprirlo.

Problemi di risoluzione del tipo

Progettazione classi potrebbe non essere in grado di risolvere i tipi per i motivi seguenti:

  • Il tipo si trova in un progetto o in un assembly a cui non viene fatto riferimento dal progetto che contiene il diagramma classi. Per correggere questo errore, aggiungere un riferimento al progetto o all'assembly che contiene il tipo. Per altre informazioni, vedere Gestione dei riferimenti in un progetto.

  • Il tipo non si trova nell'ambito corretto, di conseguenza Progettazione classi non è in grado di trovarlo. Verificare che nel codice non manchi un'istruzione using, imports o #include. Assicurarsi inoltre che il tipo (o un tipo correlato) non sia stato spostato dallo spazio dei nomi in cui si trovava in origine.

  • Il tipo non esiste oppure è stato impostato come commento. Per correggere questo errore, assicurarsi di non aver impostato il tipo come commento o di non averlo eliminato.

  • Il tipo si trova in una libreria a cui fa riferimento una direttiva #import. Una possibile soluzione alternativa consiste nell'aggiungere manualmente il codice generato (il file con estensione tlh) a una direttiva #include nel file di intestazione.

  • Verificare che Progettazione classi supporti il tipo inserito. Vedere Limitazioni per gli elementi di codice C++.

L'errore che si verifica più probabilmente per un problema di risoluzione dei tipi è Che codice non è stato trovato per una o più forme nel diagramma classi '<element>'. Questo messaggio di errore non indica necessariamente che il codice sia errato. Indica solo che Progettazione classi non è in grado di visualizzare il codice. Provare a eseguire le operazioni seguenti:

  • Verificare l'esistenza del tipo. Verificare di non aver involontariamente eliminato o impostato come codice il codice sorgente.

  • Provare a risolvere il tipo. Il tipo potrebbe trovarsi in un progetto o in un assembly a cui non viene fatto riferimento dal progetto che contiene il diagramma classi. Per correggere questo errore, aggiungere un riferimento al progetto o all'assembly che contiene il tipo. Per altre informazioni, vedere Gestione dei riferimenti in un progetto.

  • Verificare che il tipo si trovi nell'ambito corretto in modo che Progettazione classi possa trovarlo. Assicurarsi che nel codice non manchi un'istruzione using, imports o #include. Assicurarsi inoltre che il tipo (o un tipo correlato) non sia stato spostato dallo spazio dei nomi in cui si trovava in origine.

Suggerimento

Per altre informazioni sulla risoluzione dei problemi, vedere Errori di Progettazione classi.