Поделиться через


Работа с кодом С++ в Конструкторе классов

Конструктор классов отображает визуальную область конструктора, которая называется диаграммой классов и предоставляет визуальное преставление элементов кода в проекте. Схемы классов можно использовать для разработки и визуализации классов и других типов в проекте.

Конструктор классов поддерживает следующие элементы кода C++:

  • Класс (похож на фигуру управляемого класса, за исключением того, что он может иметь несколько отношений наследования)

  • Анонимный класс (отображает созданное представлением класса имя для анонимного типа)

  • Класс шаблона

  • Структура

  • Перечисление

  • Макрос (отображает представление макроса после обработки)

  • Typedef

Примечание.

Это не аналог схемы классов UML, которую можно создать в проекте моделирования. Дополнительные сведения см. в разделе UML-схемы классов: справочник.

Классы проектирования C++ в конструкторе классов

Конструктор классов поддерживает классы C++ и визуализирует собственные классы C++ так же, как фигуры классов Visual Basic и C#. Отличие состоит в том, что классы C++ могут обладать отношениями множественного наследования. Фигуру класса можно развернуть, чтобы отобразить дополнительные поля и методы класса, а также свернуть в целях экономии места.

Примечание.

Конструктор классов не поддерживает объединения (это особый тип класса, в котором объем выделяемой памяти равен размеру самого большого элемента данных объединения).

Простое наследование

Если перетащить на схему сразу несколько классов, между которыми есть отношение наследования, они будут соединены стрелкой. Стрелка указывает в направлении базового класса. Например, если на схеме классов отображаются следующие классы, они будут соединены стрелкой, которая будет указывать от класса B на класс A:

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

Также можно перетащить на схему только класс B, щелкнуть правой кнопкой мыши его фигуру, а затем выбрать команду Показать базовые классы. В этом случае будет показан базовый класс A.

Множественное наследование

Конструктор классов поддерживает наглядное представление отношений множественного наследования. Множественное наследование используется, если у производного класса есть атрибуты более чем одного базового класса. Ниже приведен пример множественного наследования:

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

Если перетащить на схему сразу несколько классов, между которыми есть отношение множественного наследования, они будут соединены стрелкой. Стрелка указывает в направлении базовых классов.

Чтобы просмотреть классы, которые являются базовыми для выбранного, щелкните правой кнопкой мыши фигуру класса и выберите Показать базовые классы.

Примечание.

Команда Показать производные классы в коде C++ не поддерживается. Чтобы просмотреть производные классы, перейдите в представление классов, разверните узел типа, затем разверните вложенную папку Производные типы и перетащите нужные типы на диаграмму классов.

Дополнительные сведения о множественном наследовании классов см. в разделах Множественное наследование и Несколько базовых классов.

Абстрактные классы

Конструктор классов поддерживает абстрактные классы (также называются "абстрактными базовыми классами"). Для этих классов не создаются экземпляры, но от них могут наследоваться другие классы. Используя пример из раздела "Множественное наследование" этого документа, вы можете создавать экземпляры класса Bird в виде отдельных объектов, как показано ниже:

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

Тем не менее вы не можете создавать экземпляры класса Swimmer в виде отдельных объектов. При этом вы можете создавать на его основе производные классы, например Penguin, Whale и Fish. В этом случае можно объявить Swimmer как абстрактный базовый класс.

Чтобы объявить класс как абстрактный, используйте ключевое слово abstract. Элементы, помеченные как абстрактные или включенные в абстрактный класс, являются виртуальными и должны быть реализованы классами, производными от абстрактного класса.

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

Также можно объявить класс как абстрактный, включив по крайней мере одну чисто виртуальную функцию:

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

При выводе этих объявлений на схеме классов имена класса Swimmer и его чисто виртуальной функции swim отображаются курсивом на фигуре абстрактного класса. Кроме того, будет показана надпись Абстрактный класс. Обратите внимание, что фигуры типа абстрактного класса аналогичны обычным классам, но их границы показаны пунктирной линией.

В классе, производном от абстрактного базового класса, необходимо переопределить каждую чисто виртуальную функцию в базовом классе. В противном случае создать экземпляр производного класса нельзя. Например, если необходимо наследовать класс Fish от класса Swimmer, в классе Fish необходимо переопределить метод swim:

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

int main()
{
   Fish guppy;
}

При отображении данного кода на диаграмме классов конструктор классов проводит линию наследования от класса Fish к классу Swimmer.

Анонимные классы

Конструктор классов поддерживает анонимные классы. Типы анонимных классов объявляются без идентификатора. Они не могут иметь конструктор или деструктор, не могут передаваться в качестве аргументов в функции и не возвращаются в качестве значений из функций. Анонимный класс можно использовать для замены имени класса именем определения типа, как показано в следующем примере:

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

Структуры также могут быть анонимными. Конструктор классов отображает анонимные классы и структуры таким же образом, как и соответствующие типы. Несмотря на то, что можно объявить и отобразить анонимные классы и структуры, конструктор классов не будет использовать указанное имя тега. В этом случае будет использоваться имя, созданное в представлении классов. Класс или структура отображаются в представлении классов и конструкторе классов в виде элемента с именем __unnamed.

Дополнительные сведения об анонимных классах см. в разделе Типы анонимных классов.

Классы шаблона

Конструктор классов поддерживает визуализацию классов шаблона. Поддерживаются вложенные объявления. В следующей таблице показаны некоторые типичные объявления.

Элемент кода Представление конструктора классов
template <class T>

class A {};
A<T>

Класс шаблона
template <class T, class U>

class A {};
A<T, U>

Класс шаблона
template <class T, int i>

class A {};
A<T, i>

Класс шаблона
template <class T, template <class K> class U>

class A {};
A<T, U>

Класс шаблона

В следующей таблице показаны некоторые примеры частичной специализации.

Элемент кода Представление конструктора классов
template<class T, class U>

class A {};
A<T, U>

Класс шаблона
template<class T>

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

Класс шаблона
template <class T>

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

Класс шаблона
template <class T1, class T2>

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

Класс шаблона

В следующей таблице показаны некоторые примеры наследования в частичной специализации.

Элемент кода Представление конструктора классов
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>

Класс шаблона

B

Класс

(указывает на класс A)

C

Класс

(указывает на класс A)

В следующей таблице приведены некоторые примеры функций шаблона частичной специализации.

Элемент кода Представление конструктора классов
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 перегрузка)
template <class T1>

class A {

template <class T2>

class B {};

};

template<> template<>

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

Класс шаблона

B<T2>

Класс шаблона

(Класс B содержится в классе A в разделе Вложенные типы)
template <class T>

class C {};

class A : C<int> {};
A

Класс

-> C<int>

C<T>

Класс шаблона

В следующей таблице показаны некоторые примеры наследования шаблонов.

Элемент кода Представление конструктора классов
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

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

Класс

->B

C<int>

Класс

(Класс B содержится в классе C в разделе Вложенные типы)

C<T>

Класс шаблона

В следующей таблице показаны некоторые примеры связей между классами в канонической специализации.

Элемент кода Представление конструктора классов
template <class T>

class C {};

template<>

class C<int> {};

class A : C<int> {};

class D : C<float> {};
A

Класс

->C<int>

C<int>

Класс

C<T>

Класс шаблона

D

Класс

->C<float>
class B {

template <class T>

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

};
B

min <T>

Перечисления C++ в конструкторе классов

Конструктор классов поддерживает типы C++ enum и типы enum class с областью видимости. Ниже приведен пример:

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

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

Фигура перечисления C++ в схеме классов выглядит и работает подобно фигуре структуры, за исключением того, что она называется Перечисление или Класс перечисления, имеет розовый, а не синий цвет, и располагает цветной границей на левом и верхнем полях. Фигуры перечисления и структуры имеют прямые углы.

Дополнительные сведения об использовании типа enum см. в статье Enumerations (Перечисления).

Определения типов C++ в конструкторе классов

Операторы typedef создают один или несколько уровней косвенного обращения между именем и его базовым типом. Конструктор классов поддерживает те определения типов C++, которые объявлены с ключевым словом typedef, например:

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

Затем можно использовать этот тип для объявления экземпляра:

COORD OriginPoint;

Фигуры для классов и структур

В конструкторе классов определение типа C++ имеет форму типа, указанного в определении типа. Если источник объявляет typedef class, у фигуры будут скругленные углы и метка класса. У typedef struct фигура имеет квадратные углы и метку Структура.

Классы и структуры могут иметь вложенные определения типов, объявленные внутри них. В конструкторе классов фигуры классов и структур могут отображать вложенные объявления определений типов в виде вложенных фигур.

Фигуры определения типов поддерживают команды Показывать как ассоциацию и Показывать как ассоциацию наборов контекстного меню.

Пример определения типа класса

class B {};
typedef B MyB;

C++ class typedef in Class Designer

Пример определения типа структуры

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

C++ struct typedef in Class Designer

Неименованные определения типов

Несмотря на то, что можно объявить определение типа без имени, конструктор классов не будет использовать указываемое имя тега. Конструктор классов будет использовать имя, созданное в представлении классов. Например, следующее объявление является допустимым, но оно отображается в представлении классов и конструкторе классов как объект с именем __unnamed:

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

Примечание.

Конструктор классов не отображает определение типа, если его исходный тип является указателем на функцию.

Сведения об ограничениях для элементов кода C++

  • При загрузке проекта на С++ конструктор классов работает в режиме только для чтения. Вы можете изменить схему классов, но не можете сохранить изменения из схемы классов обратно в исходный код.

  • Конструктор классов поддерживает только собственную семантику C++. Для проектов C++, которые компилируются в управляемый код, конструктор классов будет визуализировать только те элементы кода, которые являются собственными типами. Таким образом, вы можете добавить диаграмму классов в проект, но конструктор классов не позволит визуализировать элементы, в которых свойству IsManaged задано значение true (то есть типы значений и ссылочные типы).

  • Для проектов C++ конструктор классов считывает только определение типа. Например, предположим, что вы определяете тип в файле заголовков (H) и определяете его члены в файле реализации (CPP). При выполнении команды "Просмотр схемы класса" для файла реализации (CPP) конструктор класса не отображает ничего. Еще один пример, если вы выполняете команду "Просмотр схемы класса" для CPP-файла, который использует оператор #include для включения других файлов, но не содержит фактические определения классов, конструктор класса снова не отображает ничего.

  • IDL-файлы, которые определяют COM-интерфейсы и библиотеки типов, не отображаются в схемах, пока не будут скомпилированы в машинный код C++.

  • Конструктор классов не поддерживает глобальные функции и переменные.

  • Конструктор классов не поддерживает объединения. Это особый тип класса, в котором объем выделяемой памяти равен размеру самого большого элемента данных объединения.

  • intКонструктор классовchar не отображает базовые типы данных, такие как и .

  • Конструктор классов не отображает типы, которые определены за пределами текущего проекта, если только проект не содержит правильные ссылки на эти типы.

  • Конструктор классов может отобразить вложенные типы, но не отношения между вложенным типом и другими типами.

  • Конструктор классов не может отобразить типы, которые относятся к void или являются производными от типа void.

Устранение неполадок при разрешении типов и отображение проблем

Расположение исходных файлов

Конструктор классов не отслеживает расположение исходных файлов. Таким образом, при изменении структуры проекта или перемещении исходных файлов в проекте конструктор классов может потерять тип (особенно исходный тип определения типа, базовых классов или типов связи). Может возникнуть ошибка, например Конструктору классов не удалось отобразить этот тип. В этом случае перетащите измененный или перемещенный исходный код в схему классов и повторно отобразите ее.

Проблемы с обновлением и производительностью

Для проектов Visual C++ для отображения изменения в исходном файле на схеме классов может потребоваться от 30 до 60 секунд. Из-за такой задержки конструктор классов может выдать ошибку В выбранном блоке не найдены типы. После возникновения подобной ошибки нажмите кнопку Отмена в сообщении об ошибке и дождитесь отображения элемента кода в представлении классов. После этого конструктор классов должен быть в состоянии отобразить этот тип.

Если схема классов не обновляется для вывода внесенных в код изменений, может потребоваться закрыть схему и снова открыть ее.

Проблемы разрешения типа

Конструктор классов может оказаться не в состоянии разрешить типы по следующим причинам:

  • Тип находится в проекте или сборке, на которые нет ссылок из проекта, содержащего эту схему классов. Чтобы исправить эту ошибку, добавьте ссылку на проект или сборку, содержащие данный тип. Дополнительные сведения см. в статье Управление ссылками в проекте.

  • Тип находится в неправильной области действия, поэтому конструктор классов не может его найти. Убедитесь, что в коде присутствует оператор using, imports или #include. Убедитесь также, что этот тип (или связанный тип) не был перемещен из пространства имен, в котором он находился изначально.

  • Тип не существует (или был закомментирован). Чтобы исправить эту ошибку, убедитесь, что тип не закомментирован и не удален.

  • Тип находится в библиотеке, на которую ссылается директива #import. В качестве возможного обходного пути можно вручную добавить сформированный код (TLH-файл) в директиву #include в файле заголовка.

  • Убедитесь, что конструктор классов поддерживает введенный вами тип. См . ограничения для элементов кода C++.

Скорее всего, проблема разрешения типов возникает, если код не найден для одной или нескольких фигур в схеме классов "<элемент>". Это сообщение об ошибке не обязательно означает, что код содержит ошибку. Оно указывает лишь на то, что конструктору классов не удалось отобразить код. Попробуйте сделать следующее.

  • Убедитесь, что тип существует. Убедитесь, что исходный код не был случайно закомментирован или удален.

  • Попытайтесь разрешить тип. Тип может находиться в проекте или сборке, на которые нет ссылок из проекта, содержащего эту схему классов. Чтобы исправить эту ошибку, добавьте ссылку на проект или сборку, содержащие данный тип. Дополнительные сведения см. в статье Управление ссылками в проекте.

  • Убедитесь, что тип находится в правильной области действия, чтобы конструктор классов мог его найти. Убедитесь, что в коде присутствует оператор using, imports или #include. Убедитесь также, что этот тип (или связанный тип) не был перемещен из пространства имен, в котором он находился изначально.

Совет

Дополнительные сведения об устранении неполадок см. в разделе об ошибках конструктора классов.