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