类设计器 显示名为 类图 的视觉设计图面,该图提供项目中代码元素的可视表示形式。 可以使用类图来设计和可视化项目中的类和其他类型。
类设计器 支持以下C++代码元素:
类(类似于托管类形状,不同之处在于它可以具有多个继承关系)
匿名类(显示匿名类型的类视图生成的名称)
模板类
结构
Enum
宏(显示宏的后处理视图)
Typedef
注释
这与可以在建模项目中创建的 UML 类图不同。 有关详细信息,请参阅 UML 类图:参考。
类设计器中的C++类
类设计器 支持C++类,并采用与 Visual Basic 和 C# 类形状相同的方式可视化本机C++类,但C++类可以具有多个继承关系。 可以展开类形状以显示类中的更多字段和方法,或将其折叠以节省空间。
注释
类设计器 不支持联合(一种特殊类型的类,其中分配的内存只是联合的最大数据成员所需的量)。
简单继承
将多个类拖到类图上并且类具有类继承关系时,箭头会连接它们。 箭头指向基类的方向。 例如,当类关系图中显示以下类时,箭头会连接它们,从 B 指向 A:
class A {};
class B : A {};
还可以仅将类 B 拖动到类图中,右键单击 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 名称,如以下示例所示:
typedef struct
{
unsigned x;
unsigned y;
} POINT;
结构也可以是匿名的。 类设计器 显示匿名类和结构,与显示其对应类型的方式相同。 虽然可以声明和显示匿名类和结构, 但类设计器 不会使用指定的标记名称。 它将使用类视图生成的名称。 类或结构作为名为__unnamed的元素显示在类视图和类设计器中。
有关匿名类的详细信息,请参阅 匿名类类型。
模板类
类设计器 支持模板类的可视化效果。 支持嵌套声明。 下表显示了一些典型的声明。
| Code 元素 | 类设计器视图 |
|---|---|
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>模板类 |
下表显示了部分专用化的一些示例。
| Code 元素 | 类设计器视图 |
|---|---|
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*>模板类 |
下表展示了一些关于部分特化中继承的示例。
| Code 元素 | 类设计器视图 |
|---|---|
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>模板类 BClass (指向 A 类) CClass (指向 A 类) |
下表显示了部分专用化模板函数的一些示例。
| Code 元素 | 类设计器视图 |
|---|---|
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 重载) |
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> {}; |
AClass -> C<int> C<T>模板类 |
下表显示了模板继承的一些示例。
| Code 元素 | 类设计器视图 |
|---|---|
template <class T>class C {};template<>class C<int> {class B {};}class A : C<int>::B {}; |
AClass ->B C<int>Class (B 包含在 嵌套类型下的类 C 中) C<T>模板类 |
下表显示了规范专用类连接的一些示例。
| Code 元素 | 类设计器视图 |
|---|---|
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>模板类 DClass ->C<float> |
class B {template <class T>T min (const T &a, const T &b);}; |
Bmin <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或Enum 类,其颜色为粉红色,区别于蓝色,并且它在左边和上边距上有彩色边框。 枚举形状和结构形状都有方角。
有关使用 enum 类型的详细信息,请参阅 枚举。
类设计器中的 C++ 类型定义
Typedef 语句在名称及其基础类型之间创建一个或多个间接层。
类设计器 支持C++ typedef 类型,这些类型使用关键字 typedef声明,例如:
typedef class coord
{
void P(x,y);
unsigned x;
unsigned y;
} COORD;
然后,可以使用此类型声明实例:
COORD OriginPoint;
类和结构形状
在 类设计器中,C++ typedef 具有 typedef 中指定的类型的形状。 如果源声明 typedef class,则形状具有圆角和标签 类。 对于 typedef struct,形状具有方角和标签 结构。
类和结构体可以声明嵌套的“typedef”。 在 类设计器中,类和结构形状可以将嵌套 typedef 声明显示为嵌套形状。
Typedef 形状支持右键单击菜单上的 “显示为关联 ”和 “显示为集合关联 ”命令(上下文菜单)。
类 typedef 示例
class B {};
typedef B MyB;
结构 typedef(类型定义)示例
typedef struct mystructtag
{
int i;
double f;
} mystruct;
未命名的 typedefs
虽然可以声明没有名称的 typedef,但 类设计器 不使用您指定的标签名称。 类设计器 使用 类视图 生成的名称。 例如,以下声明有效,但它在 类视图 和 类设计器 中显示为名为 __unnamed的对象:
typedef class coord
{
void P(x,y);
unsigned x;
unsigned y;
};
注释
类设计器 不显示其源类型为函数指针的 typedefs。
了解C++代码元素的限制
加载C++项目时, 类设计器 以只读方式运行。 可以更改类图,但无法将类图中的更改保存回源代码。
类设计器 仅支持本机C++语义。 对于编译为托管代码的C++项目, 类设计器 将仅可视化属于本机类型的代码元素。 因此,可以将类图添加到项目中,但类设计器将不允许您对其属性设置为
true的元素(即值类型和引用类型)进行可视化。对于C++项目, 类设计器 仅读取类型的定义。 例如,假设你在标头 (.h) 文件中定义一个类型,并在实现 (.cpp) 文件中定义其成员。 如果在实现(.cpp)文件中调用“查看类图”, 类设计器 将不显示任何内容。 作为另一个示例,如果在.cpp文件上调用“查看类图”,该文件使用
#include语句包含其他文件但不包含任何实际类定义,那么类设计器 将依然不显示任何内容。定义 COM 接口和类型库的 IDL (.idl) 文件不会显示在关系图中,除非它们编译为本机C++代码。
类设计器 不支持全局函数和变量。
类设计器 不支持联合。 这是一种特殊类型的类,其中分配的内存只是联合体最大的数据成员所需的量。
类设计器 不显示基本数据类型,如
int和char。如果项目没有对这些类型的正确引用,则类设计器不会显示当前项目外部定义的类型。
类设计器 可以显示嵌套类型,但不能显示嵌套类型与其他类型的关系。
类设计器 无法显示 void 类型或派生自 void 类型的类型。
解决类型解析和显示问题
源文件的位置
类设计器 不会跟踪源文件的位置。 因此,如果修改项目结构或移动项目中的源文件, 类设计器 可能会失去类型(尤其是 typedef、基类或关联类型的源类型)的跟踪。 你可能会收到错误,例如 类设计器无法显示此类型。 如果这样做,请将修改的源代码或重新定位的源代码再次拖动到类图中以重新显示它。
更新和性能问题
对于C++项目,源文件中的更改可能需要 30 到 60 秒才能显示在类图中。 此延迟还可能导致 类设计器 引发 错误:在所选内容中找不到任何类型。 如果收到此类错误,请单击错误消息中的“ 取消 ”,并等待代码元素显示在 类视图中。 执行此作后, 类设计器 应能够显示类型。
如果类图未更新您在代码中所做的更改,则可能需要关闭类图并重新打开它。
类型解析问题
由于以下原因,类设计器可能无法解析类型:
该类型位于未被包含类图的项目引用的其他项目或程序集内。 若要更正此错误,请添加对包含该类型的项目或程序集的引用。 有关详细信息,请参阅 管理项目中的引用。
该类型不在正确的范围内,因此 类设计器 无法找到它。 确保代码中没有缺少
using、imports或#include语句。 此外,请确保尚未将类型(或相关类型)移出最初所在的命名空间。该类型不存在(或已被注释掉)。 若要更正此错误,请确保你没有注释掉或删除该类型。
该类型位于由 #import 指令引用的库中。 可能的解决方法是将生成的代码(.tlh 文件)手动添加到头文件中的 #include 指令。
确保 类设计器 支持输入的类型。 请参阅 C++代码元素的限制。
对于类型解析问题,你最有可能看到的错误是类图“<element>”中的一个或多个形状找不到代码。 此错误消息不一定指示代码出错。 它仅指示类设计器无法显示您的代码。 请尝试以下措施:
确保类型存在。 确保你无意中注释掉或删除了源代码。
尝试解析类型。 该类型可能位于不包含类关系图的项目或程序集中。 若要更正此错误,请添加对包含该类型的项目或程序集的引用。 有关详细信息,请参阅 管理项目中的引用。
确保类型位于正确的范围内,以便类设计器可以找到它。 确保代码未缺少
using、imports或#include语句。 此外,请确保尚未将类型(或相关类型)移出最初所在的命名空间。
小窍门
有关其他故障排除信息,请参阅 类设计器错误。