Partilhar via


Trabalhar com código C++ no Designer de Classe

O Designer de Classe exibe uma superfície de design visual chamada de diagrama de classe que fornece uma representação visual dos elementos de código no projeto. É possível usar diagramas de classe para criar e visualizar classes e outros tipos em um projeto.

O Designer de Classe é compatível com os seguintes elementos de código C++:

  • Classe (semelhante a uma forma de classe gerenciada, com exceção de que ela pode ter vários relacionamentos de herança)

  • Classe anônima (exibe o nome gerado do Modo de Exibição de Classe para o tipo anônimo)

  • Classe de modelo

  • Estrutura

  • Enumeração

  • Macro (exibe a exibição pós-processada da macro)

  • Typedef

Observação

Isso não é o mesmo que o diagrama de classe UML, que pode ser criado em um Projeto de Modelagem. Para obter mais informações, consulte Diagramas de classe UML: Referência.

Classes C++ no Designer de Classe

O Designer de Classe é compatível com classes do C++ e visualiza classes nativas do C++ da mesma maneira que as formas de classe do Visual Basic e do C#, exceto que as classes do C++ podem ter várias relações de herança. É possível expandir a forma de classe para exibir mais campos e métodos na classe ou recolhê-la para economizar espaço.

Observação

O Designer de Classe não é compatível com uniões (um tipo especial de classe em que a memória alocada é apenas a quantidade necessária para o maior membro de dados da união).

Herança simples

Quando você arrasta mais de uma classe para um diagrama de classe e as classes têm uma relação de herança de classe, uma seta as conecta. A seta aponta para a direção da classe base. Por exemplo, quando as classes a seguir são exibidas em um diagrama de classe, uma seta as conecta, apontando de B para A:

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

Você também pode arrastar apenas a classe B para o diagrama de classe, clicar com o botão direito do mouse na forma de classe de B e, em seguida, clicar em Mostrar Classes Base. Isso exibe sua classe base: A.

Herança múltipla

O Designer de Classe é compatível com a visualização de relações de herança com várias classes. A herança múltipla é usada quando uma classe derivada tem atributos com mais de uma classe base. A seguir, temos um exemplo de herança múltipla:

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

Quando você arrasta mais de uma classe para o diagrama de classe e as classes têm uma relação de herança com várias classes, uma seta as conecta. A seta aponta para a direção das classes base.

Clicar com o botão direito do mouse em uma forma de classe e, depois, clicar em Mostrar Classes Base exibe as classes base da classe selecionada.

Observação

O comando Mostrar Classes Derivadas não tem suporte para código C++. É possível exibir as classes derivadas acessando o Modo de Exibição de Classe, expandindo o nó de tipo, expandindo a subpasta Tipos Derivados e, em seguida, arrastando esses tipos para o diagrama de classe.

Para obter mais informações sobre a herança de classes múltiplas, consulte Herança múltipla e Classes Base Múltiplas.

Classes abstratas

O Designer de Classe é compatível com classes abstratas (também chamadas de "classes base abstratas"). Essas são classes que você nunca instancia, mas das quais pode derivar outras classes. Usando um exemplo de "Herança múltipla" no início deste documento, você pode instanciar a classe Bird como objetos individuais, da seguinte maneira:

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

No entanto, talvez você não pretenda instanciar a classe Swimmer como objetos individuais. Talvez você pretenda apenas derivar outros tipos de classes de animal, por exemplo, Penguin, Whale e Fish. Nesse caso, você declararia a classe Swimmer como uma classe base abstrata.

Para declarar uma classe como abstrata, você pode usar a palavra-chave abstract. Membros marcados como abstratos, ou incluídos em uma classe abstrata, são virtuais e devem ser implementados por classes que derivam da classe abstrata.

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

Você também pode declarar uma classe como abstrata incluindo pelo menos uma função virtual pura:

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

Quando você exibe essas declarações em um Diagrama de Classe, o nome da classe Swimmer e sua função virtual pura swim são exibidos em itálico em uma forma de classe abstrata, em conjunto com a notação Classe Abstrata. Observe que a forma do tipo de classe abstrata é a mesmo de uma classe regular, mas sua borda é uma linha pontilhada.

Uma classe derivada de uma classe base abstrata deve substituir cada função virtual pura na classe base, ou a classe derivada não poderá ser instanciada. Portanto, por exemplo, se você derivar uma classe Fish da classe Swimmer, Fish deverá substituir o método swim:

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

int main()
{
   Fish guppy;
}

Quando você exibe esse código em um Diagrama de Classe, o Designer de Classe desenha uma linha de herança de Fish para Swimmer.

Classes anônimas

O Designer de Classe é compatível com classes anônimas. Tipos de classe anônima são classes declaradas sem um identificador. Elas não podem ter um construtor ou um destruidor, não podem ser passadas como argumentos para funções e não podem ser retornadas como valores retornados de funções. É possível usar uma classe anônima para substituir um nome de classe por um nome de typedef, como no exemplo a seguir:

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

As estruturas também podem ser anônimas. O Designer de Classe exibe estruturas e classes anônimas da mesma forma que exibe o respectivo tipo. Embora você possa declarar e exibir estruturas e classes anônimas, o Designer de Classe não usará o nome de marca que você especificar. Ele usará o nome gerado pelo Modo de Exibição de Classe. A classe ou a estrutura aparece no Modo de Exibição de Classe e no Designer de Classe como um elemento chamado __unnamed.

Para obter mais informações sobre classes anônimas, consulte Tipos de classe anônima.

Classes de modelo

O Designer de Classe é compatível com a visualização de classes de modelo. Declarações aninhadas têm suporte. A tabela a seguir mostra algumas declarações típicas.

Elemento de código Modo de exibição do Designer de Classe
template <class T>

class A {};
A<T>

Classe de modelo
template <class T, class U>

class A {};
A<T, U>

Classe de modelo
template <class T, int i>

class A {};
A<T, i>

Classe de modelo
template <class T, template <class K> class U>

class A {};
A<T, U>

Classe de modelo

A tabela a seguir mostra alguns exemplos de especialização parcial.

Elemento de código Modo de exibição do Designer de Classe
template<class T, class U>

class A {};
A<T, U>

Classe de modelo
template<class T>

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

Classe de modelo
template <class T>

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

Classe de modelo
template <class T1, class T2>

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

Classe de modelo

A tabela a seguir mostra alguns exemplos de herança na especialização parcial.

Elemento de código Modo de exibição do Designer de Classe
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 de modelo

B

Classe

(aponta para a Classe A)

C

Classe

(aponta para a Classe A)

A tabela a seguir mostra alguns exemplos de funções de modelo de especialização parcial.

Elemento de código Modo de exibição do Designer de Classe
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 de sobrecarga)
template <class T1>

class A {

template <class T2>

class B {};

};

template<> template<>

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

Classe de modelo

B<T2>

Classe de modelo

(B está contido na classe A em Tipos Aninhados)
template <class T>

class C {};

class A : C<int> {};
A

Classe

-> C<int>

C<T>

Classe de modelo

A tabela a seguir mostra alguns exemplos de herança de modelo.

Elemento de código Modo de exibição do Designer de Classe
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

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

Classe

->B

C<int>

Classe

(B está contido na classe C em Tipos Aninhados)

C<T>

Classe de modelo

A tabela a seguir mostra alguns exemplos de conexões de classe especializada canônicas.

Elemento de código Modo de exibição do Designer de Classe
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 de modelo

D

Classe

->C<float>
class B {

template <class T>

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

};
B

min <T>

Enumerações do C++ no Designer de Classe

O Designer de Classe é compatível com os tipos enum e enum class no escopo do C++. A seguir está um exemplo:

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

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

Uma forma de enumeração do C++ em um diagrama de classes parece e funciona como uma forma de estrutura, exceto pelo seguinte: o rótulo exibe Enum ou Enum class, ele é rosa em vez de azul e tem uma borda colorida nas margens esquerda e superior. As formas de enumeração e formas de estrutura tem cantos quadrados.

Para obter mais informações sobre o uso do tipo enum, consulte Enumerações.

Typedefs C++ no Designer de Classe

As instruções typedef criam uma ou mais camadas de indireção entre um nome e seu tipo subjacente. O Designer de Classe é compatível com tipos de typedef do C++ declarados com a palavra-chave typedef, por exemplo:

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

Então, você pode usar esse tipo para declarar uma instância:

COORD OriginPoint;

Formas de classe e de struct

No Designer de Classe, um typedef do C++ tem a forma do tipo especificado no typedef. Se a fonte declarar typedef class, a forma terá cantos arredondados e o rótulo Classe. Para typedef struct, a forma tem cantos quadrados e o rótulo Struct.

Classes e estruturas podem ter typedefs aninhados declarados dentro delas. No Designer de Classe, formas de classe e de estrutura podem mostrar declarações de typedef aninhado como formas aninhadas.

As formas typedef oferecem suporte aos comandos Mostrar como Associação e Mostrar como Associação de Coleções no menu do clique com o botão direito (menu de contexto).

Exemplo do typedef de classe

class B {};
typedef B MyB;

C++ class typedef in Class Designer

Exemplo do typedef de struct

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

C++ struct typedef in Class Designer

Typedefs sem nome

Embora seja possível declarar um typedef sem um nome, o Designer de Classe não usará o nome da marca especificada. O Designer de Classe use o nome gerado pelo Modo de Exibição de Classe. Por exemplo, a declaração a seguir é válida, mas ela aparece no Modo de Exibição de Classe e no Designer de Classe como um objeto chamado __unnamed:

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

Observação

O Designer de Classe não exibe typedefs cujo tipo de origem é um ponteiro de função.

Saiba mais sobre limitações para elementos de código C++

  • Quando um projeto C++ é carregado, o Designer de Classe funciona em modo somente leitura. É possível alterar o diagrama de classe, mas não é possível salvar alterações do diagrama de classe de volta no código-fonte.

  • O Designer de Classe é compatível com somente a semântica nativa do C++. Para projetos C++ compilados em código gerenciado, o Designer de Classe visualizará apenas os elementos de código que forem tipos nativos. Portanto, é possível adicionar um diagrama de classe a um projeto, mas o Designer de Classe não permitirá a visualização de elementos nos quais a propriedade IsManaged esteja definida como true (ou seja, tipos de valor e tipos de referência).

  • Para projetos C++, o Designer de Classe lê somente a definição do tipo. Por exemplo, suponha que você defina um tipo em um arquivo de cabeçalho (.h) e defina seus membros em um arquivo de implementação (.cpp). Se você invocar “Exibir Diagrama de Classe” no arquivo de implementação (.cpp), o Designer de Classe não exibirá nada. Como outro exemplo, se você invocar “Exibir Diagrama de Classe” em um arquivo .cpp que use uma instrução #include para incluir outros arquivos, mas que não contenha nenhuma definição de classe real, o Designer de Classe não exibirá nada novamente.

  • Arquivos IDL (.idl), que definem interfaces COM e bibliotecas de tipo, não exibem diagramas, a menos que sejam compilados para o código C++ nativo.

  • O Designer de Classe não é compatível com funções e variáveis globais.

  • Designer de Classe não é compatível com uniões. Esse é um tipo especial de classe no qual a memória alocada é apenas a quantidade necessária para o maior membro de dados da união.

  • O Designer de Classe não exibe tipos de dados básicos como int e char.

  • O Designer de Classe não exibe tipos que são definidos fora do projeto atual se o projeto não tem referências corretas para esses tipos.

  • O Designer de Classe pode exibir tipos aninhados, mas não as relações entre um tipo aninhado e outros tipos.

  • O Designer de Classe não pode exibir tipos que são nulos ou derivados de um tipo nulo.

Solucionar problemas de exibição e resolução de tipo

Local dos arquivos de origem

O Designer de Classe não mantém um controle sobre a localização dos arquivos de origem. Portanto, se você modificar a estrutura do projeto ou mover os arquivos de origem no projeto, o Designer de Classe poderá perder o controle do tipo (principalmente do tipo de origem de um typedef, de classes base ou de tipos de associação). É possível receber um erro como O Designer de Classe não pode exibir este tipo. Se você fizer isso, arraste o código-fonte realocado ou modificado para o diagrama de classe, para exibi-lo novamente.

Problemas de atualização e de desempenho

Para projetos C++, pode levar de 30 a 60 segundos para que uma alteração no arquivo de origem seja exibida no diagrama de classe. Esse atraso também pode fazer com que o Designer de Classe gere o erro Não foi encontrado nenhum tipo na seleção. Se você receber um erro como esse, clique em Cancelar na mensagem de erro e espere até que o elemento de código seja exibido no Modo de Exibição de Classe. Depois de fazer isso, o Designer de Classe deverá exibir o tipo.

Se um diagrama de classe não for atualizado com as alterações feitas no código, talvez seja necessário fechar o diagrama e abri-lo novamente.

Problemas de resolução de tipo

O Designer de Classe pode não conseguir resolver tipos pelos seguintes motivos:

  • O tipo está em um projeto ou assembly que não é referenciado no projeto que contém o diagrama de classe. Para corrigir esse erro, adicione uma referência ao projeto ou ao assembly que contém o tipo. Para obter mais informações, consulte Gerenciando referências em um projeto.

  • O tipo não está no escopo correto e, portanto, o Designer de Classe não pode localizá-lo. Verifique se o código não tem uma declaração using, imports ou #include ausente. Além disso, verifique se você não moveu o tipo (ou um tipo relacionado) para fora do namespace em que ele estava originalmente localizado.

  • O tipo não existe (ou foi comentado). Para corrigir esse erro, verifique se você não comentou nem excluiu o tipo.

  • O tipo está localizado em uma biblioteca referenciada por uma diretiva #import. Uma possível solução alternativa é adicionar o código gerado (o arquivo .tlh) manualmente a uma diretiva #include no arquivo de cabeçalho.

  • Verifique se o Designer de Classe é compatível com o tipo inserido. Confira Limitações de elementos de código C++.

O erro que provavelmente você receberá para um problema de resolução de tipo é Não foi possível encontrar o código em uma ou mais formas no diagrama de classe '<element>'. Essa mensagem de erro não indica necessariamente que o código tem um erro. Ela indica apenas que o designer de classe não pôde exibir o código. Tente as seguintes medidas:

  • Verifique se o tipo existe. Verifique se você não comentou nem excluiu o código-fonte acidentalmente.

  • Tente resolver o tipo. O tipo pode estar em um projeto ou assembly que não é referenciado no projeto que contém o diagrama de classe. Para corrigir esse erro, adicione uma referência ao projeto ou ao assembly que contém o tipo. Para obter mais informações, consulte Gerenciando referências em um projeto.

  • Verifique se o tipo está no escopo correto para que o Designer de Classe possa localizá-lo. Verifique se o código não tem uma declaração using, imports ou #include ausente. Além disso, verifique se você não moveu o tipo (ou um tipo relacionado) para fora do namespace em que ele estava originalmente localizado.

Dica

Para obter informações adicionais de solução de problemas, confira Erros do Designer de Classe.