Compartir a través de


Trabajar con código de C++ en el Diseñador de clases

El Diseñador de clases muestra una superficie de diseño visual denominada diagrama de clases que proporciona una representación visual de los elementos de código del proyecto. Puede usar diagramas de clases para diseñar y visualizar clases y otros tipos en un proyecto.

El Diseñador de clases admite los siguientes elementos de código de C++:

  • Clase (se parece a una forma de clase administrada, excepto que puede tener varias relaciones de herencia)

  • Clase anónima (muestra el nombre generado de la vista de clases para el tipo anónimo)

  • Clase de plantilla

  • Estructura

  • Enum

  • Macro (muestra la vista posterior al procesamiento de la macro)

  • Definición de tipo

Nota:

Esto no es lo mismo que el diagrama de clases UML, que puede crear en un proyecto de modelado. Para obtener más información, vea Diagramas de clases UML: Referencia.

Clases de C++ en el Diseñador de clases

El Diseñador de clases admite clases de C++ y visualiza clases nativas de C++ de la misma manera que las formas de clase de Visual Basic y C#, salvo que las clases de C++ pueden tener varias relaciones de herencia. Puede expandir la forma de clase para mostrar más campos y métodos en la clase o contraerla para conservar espacio.

Nota:

El Diseñador de clases no admite uniones (un tipo especial de clase en la que la memoria asignada es solo la cantidad necesaria para el miembro de datos más grande de la unión).

Herencia simple

Al arrastrar más de una clase a un diagrama y existir una relación de herencia entre ellas, una flecha las conectará. La flecha apunta en la dirección de la clase base. Por ejemplo, cuando se muestran las siguientes clases en un diagrama de clases, una flecha las conecta, apuntando de B a A:

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

También puede arrastrar solo la clase B al diagrama de clases, hacer clic con el botón derecho en la forma de clase de B y, a continuación, hacer clic en Mostrar clases base. Esto muestra su clase base: A.

Herencia múltiple

El Diseñador de clases admite la visualización de relaciones de herencia de varias clases. La herencia múltiple se usa cuando una clase derivada tiene atributos de más de una clase base. A continuación se muestra un ejemplo de herencia múltiple:

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

Al arrastrar más de una clase al diagrama de clases y las clases tienen una relación de herencia de varias clases, una flecha las conecta. La flecha apunta en la dirección de las clases base.

Al hacer clic con el botón derecho en una forma de clase y, a continuación, hacer clic en Mostrar clases base , se muestran las clases base de la clase seleccionada.

Nota:

El comando Show Derived Classes (Mostrar clases derivadas ) no es compatible con el código de C++. Para mostrar clases derivadas, vaya a Vista de clases, expanda el nodo de tipo, expanda la subcarpeta Tipos derivados y arrastre esos tipos al diagrama de clases.

Para obtener más información sobre la herencia de varias clases, vea Herencia múltiple y Varias clases base.

Clases abstractas

El Diseñador de clases admite clases abstractas (también denominadas "clases base abstractas"). Estas son clases que nunca se instancian, pero de las que se pueden derivar otras clases. Con un ejemplo de "Herencia múltiple" anteriormente en este documento, puede crear instancias de la clase Bird en forma de objetos individuales tal como se indica a continuación.

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

Sin embargo, es posible que no quiera instanciar objetos individuales de la clase Swimmer. Es posible que solo quiera derivar otros tipos de clases de animales de él, por ejemplo, Penguin, Whaley Fish. En ese caso, declararía la Swimmer clase como una clase base abstracta.

Para declarar una clase como abstracta, puede usar la abstract palabra clave . Los miembros marcados como abstractos, o incluidos en una clase abstracta, son virtuales y deben implementarse mediante clases que derivan de la clase abstracta.

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

También puede declarar una clase como abstracta si incluye al menos una función virtual pura:

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

Cuando se muestran estas declaraciones en un diagrama de clases, el nombre de la clase Swimmer y su función virtual pura swim se muestran en cursiva en una representación de clase abstracta, junto con la notación Clase abstracta. Observe que la forma de tipo de clase abstracta es la misma que la de una clase normal, excepto que su borde es una línea de puntos.

Una clase derivada de una clase base abstracta debe invalidar cada función virtual pura en la clase base o no se puede crear una instancia de la clase derivada. Por ejemplo, si deriva una Fish clase de la Swimmer clase , Fish debe invalidar el swim método :

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

int main()
{
   Fish guppy;
}

Al mostrar este código en un diagrama de clases, el Diseñador de clases dibuja una línea de herencia de Fish a Swimmer.

Clases anónimas

El Diseñador de clases admite clases anónimas. Los tipos de clase anónimos son clases declaradas sin un identificador. No pueden tener un constructor o destructor, no se pueden pasar como argumentos a funciones y no se pueden devolver como valores devueltos de funciones. Puede usar una clase anónima para reemplazar un nombre de clase por un nombre typedef, como en el ejemplo siguiente:

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

Las estructuras también pueden ser anónimas. Diseñador de Clases muestra clases anónimas y estructuras de la misma manera que muestra el tipo respectivo. Aunque puede declarar y mostrar clases y estructuras anónimas, el Diseñador de clases no usará el nombre de etiqueta que especifique. Usará el nombre que genera la vista de clase. La clase o estructura aparece en la vista de clases y el Diseñador de clases como un elemento denominado __unnamed.

Para obtener más información sobre las clases anónimas, vea Tipos de clase anónimos.

Clases de plantilla

El Diseñador de clases admite la visualización de clases de plantilla. Se admiten declaraciones anidadas. En la tabla siguiente se muestran algunas declaraciones típicas.

Elemento Code Vista del Diseñador de clases
template <class T>

class A {};
A<T>

Clase Plantilla
template <class T, class U>

class A {};
A<T, U>

Clase plantilla
template <class T, int i>

class A {};
A<T, i>

Clase Plantilla
template <class T, template <class K> class U>

class A {};
A<T, U>

Clase plantilla

En la tabla siguiente se muestran algunos ejemplos de especialización parcial.

Elemento Code Vista del diseñador de clases
template<class T, class U>

class A {};
A<T, U>

Clase de Plantilla
template<class T>

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

Clase plantilla
template <class T>

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

Clase de plantilla
template <class T1, class T2>

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

Clase plantilla

En la tabla siguiente se muestran algunos ejemplos de herencia en especialización parcial.

Elemento Code Vista del Diseñador de Clases
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>

Clase Plantilla

B

Class

(apunta a la clase A)

C

Class

(apunta a la clase A)

En la tabla siguiente se muestran algunos ejemplos de funciones de plantilla de especialización parcial.

Elemento Code Vista del Diseñador de Clases
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 sobrecarga)
template <class T1>

class A {

template <class T2>

class B {};

};

template<> template<>

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

Clase Plantilla

B<T2>

Clase plantilla

(B se encuentra dentro de la clase A en Tipos anidados)
template <class T>

class C {};

class A : C<int> {};
A

Class

-> C<int>

C<T>

Clase Plantilla

En la tabla siguiente se muestran algunos ejemplos de herencia de plantillas.

Elemento Code Vista del Diseñador de clases
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

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

Class

->B

C<int>

Class

(B se encuentra dentro de la clase C en Tipos anidados)

C<T>

Clase Plantilla

En la tabla siguiente se muestran algunos ejemplos de conexión de clases especializadas canónicas.

Elemento Code Vista del Diseñador de Clases
template <class T>

class C {};

template<>

class C<int> {};

class A : C<int> {};

class D : C<float> {};
A

Class

->C<int>

C<int>

Class

C<T>

Clase plantilla

D

Class

->C<float>
class B {

template <class T>

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

};
B

min <T>

Enumeraciones de C++ en el Diseñador de clases

Diseñador de Clases admite C++ enum y tipos delimitados enum class. A continuación se muestra un ejemplo:

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

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

Una forma de enumeración de C++ en un diagrama de clases tiene un aspecto y funciona como una forma de estructura, salvo que la etiqueta lee la clase Enum o Enum, es rosa en lugar de azul y tiene un borde coloreado en los márgenes izquierdo y superior. Las formas de enumeración y las formas de estructura tienen esquinas cuadradas.

Para obtener más información sobre el uso del enum tipo, vea Enumeraciones.

Definiciones de tipos de C++ en el Diseñador de clases

Las instrucciones Typedef crean una o varias capas de direccionamiento indirecto entre un nombre y su tipo subyacente. El Diseñador de clases admite tipos de definición de tipos de C++, que se declaran con la palabra clave typedef, por ejemplo:

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

A continuación, puede usar este tipo para declarar una instancia:

COORD OriginPoint;

Formas de clase y estructura

En el Diseñador de clases, una definición de tipo de C++ tiene la forma del tipo especificado en la definición de tipos. Si el origen declara typedef class, la forma tiene esquinas redondeadas y la etiqueta Class. Para typedef struct, la forma tiene esquinas cuadradas y la etiqueta es Struct.

Las clases y estructuras pueden tener definiciones de tipo anidadas declaradas dentro de ellas. En el Diseñador de Clases, las formas de clases y estructuras pueden mostrar declaraciones de tipo definidas como formas anidadas.

Las formas typedef admiten los comandos Mostrar como asociación y Mostrar como asociación de colección en el menú contextual.

Ejemplo de definición de tipo de clase

class B {};
typedef B MyB;

Definición de tipo de clase de C++ en el Diseñador de clases

Ejemplo de definición de tipo de estructura

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

Definición de tipo de estructura de C++ en el Diseñador de clases

Definiciones de tipos sin nombre

Aunque puede declarar una definición de tipo sin un nombre, el Diseñador de clases no usa el nombre de etiqueta que especifique. El Diseñador de clases utiliza el nombre generado por Class View. Por ejemplo, la siguiente declaración es válida, pero aparece en la Vista de clases y el Diseñador de clases como un objeto denominado __unnamed:

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

Nota:

El Diseñador de clases no muestra definiciones de tipo cuyo tipo de origen es un puntero de función.

Más información sobre las limitaciones de los elementos de código de C++

  • Cuando se carga un proyecto de C++, el Diseñador de clases funciona de solo lectura. Puede cambiar el diagrama de clases, pero no puede volver a guardar los cambios del diagrama de clases en el código fuente.

  • El Diseñador de clases solo admite la semántica nativa de C++. En el caso de los proyectos de C++ que se compilan en código administrado, el Diseñador de clases solo visualizará los elementos de código que son tipos nativos. Por lo tanto, puede agregar un diagrama de clases a un proyecto, pero el Diseñador de clases no le permitirá visualizar los elementos en los que la IsManaged propiedad está establecida true en (es decir, tipos de valor y tipos de referencia).

  • En el caso de los proyectos de C++, el Diseñador de clases solo lee la definición del tipo. Por ejemplo, supongamos que define un tipo en un archivo de encabezado (.h) y define sus miembros en un archivo de implementación (.cpp). Si invoca "Ver diagrama de clases" en el archivo de implementación (.cpp), el Diseñador de clases no muestra nada. Como otro ejemplo, si invoca "Ver diagrama de clases" en un archivo de .cpp que usa una #include instrucción para incluir otros archivos, pero no contiene ninguna definición de clase real, el Diseñador de clases vuelve a mostrar nada.

  • Los archivos IDL (.idl), que definen interfaces COM y bibliotecas de tipos, no se muestran en diagramas a menos que se compilen en código nativo de C++.

  • El Diseñador de clases no admite funciones y variables globales.

  • El Diseñador de Clases no admite uniones. Se trata de un tipo especial de clase en la que la memoria asignada es solo la cantidad necesaria para el elemento de datos más grande de la unión.

  • El Diseñador de clases no muestra tipos de datos básicos como int y char.

  • El Diseñador de clases no muestra tipos definidos fuera del proyecto actual si el proyecto no tiene referencias correctas a esos tipos.

  • El Diseñador de clases puede mostrar tipos anidados, pero no las relaciones entre un tipo anidado y otros tipos.

  • El Diseñador de clases no puede mostrar tipos que son nulos o que derivan de un tipo void.

Solucionar problemas de resolución de tipos y de visualización

Ubicación de los archivos de origen

El Diseñador de clases no realiza un seguimiento de la ubicación de los archivos de origen. Por lo tanto, si modifica la estructura del proyecto o mueve archivos de código fuente en el proyecto, el Diseñador de clases puede perder el seguimiento del tipo (especialmente el tipo de origen de una definición de tipo, clases base o tipos de asociación). Es posible que reciba un error como el Diseñador de clases no puede mostrar este tipo. Si lo hace, arrastre de nuevo el código fuente modificado o reubicado al diagrama de clases para volver a reproducirlo.

Problemas de actualización y rendimiento

En el caso de los proyectos de C++, puede tardar entre 30 y 60 segundos en aparecer un cambio en el archivo de origen en el diagrama de clases. Este retraso también puede hacer que el Diseñador de clases produzca el error No se encontraron tipos en la selección. Si recibe un error como este, haga clic en Cancelar en el mensaje de error y espere a que el elemento de código aparezca en la vista de clases. Después de hacerlo, el Diseñador de clases debe poder mostrar el tipo.

Si un diagrama de clases no se actualiza con los cambios realizados en el código, es posible que tenga que cerrar el diagrama y volver a abrirlo.

Problemas de resolución de tipos

Es posible que el Diseñador de clases no pueda resolver tipos por los siguientes motivos:

  • El tipo está en un proyecto o ensamblado al que no se hace referencia desde el proyecto que contiene el diagrama de clases. Para corregir este error, agregue una referencia al proyecto o ensamblado que contiene el tipo . Para obtener más información, vea Administración de referencias en un proyecto.

  • El tipo no está en el ámbito correcto, por lo que el Diseñador de clases no puede encontrarlo. Asegúrese de que no falte en el código una using, imports o #include instrucción. Asegúrese también de que no ha movido el tipo (o un tipo relacionado) fuera del espacio de nombres en el que se encontraba originalmente.

  • El tipo no existe (puede que ha sido comentado). Para corregir este error, asegúrese de que no ha comentado ni eliminado el tipo de dato.

  • El tipo se encuentra en una biblioteca a la que hace referencia una directiva #import. Una posible solución alternativa consiste en agregar manualmente el código generado (el archivo .tlh) a una directiva #include en el archivo de encabezado.

  • Asegúrese de que el Diseñador de clases admite el tipo especificado. Consulte Limitaciones de los elementos de código de C++.

El error que es más probable que vea para un problema de resolución de tipos es No se pudo encontrar el código para una o más formas en el diagrama de clases "<element>". Este mensaje de error no indica necesariamente que el código está en error. Indica únicamente que el diseñador de clases no pudo mostrar tu código. Pruebe las siguientes medidas:

  • Verifique que el tipo existe. Asegúrese de que no ha comentado ni eliminado involuntariamente el código fuente.

  • Intente resolver el tipo. El tipo puede estar en un proyecto o ensamblado al que no se hace referencia desde el proyecto que contiene el diagrama de clases. Para corregir este error, agregue una referencia al proyecto o ensamblado que contiene el tipo . Para obtener más información, vea Administración de referencias en un proyecto.

  • Asegúrese de que el tipo está en el ámbito correcto para que el Diseñador de clases pueda localizarlo. Asegúrese de que el código no falta una instrucción using, imports o #include. Asegúrese también de que no ha movido el tipo (o un tipo relacionado) fuera del espacio de nombres en el que se encontraba originalmente.

Sugerencia

Para obtener información adicional sobre la solución de problemas, consulte Errores del Diseñador de clases.