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 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
语句。 还请确保未将该类型(或相关类型)移出它原来所在的命名空间。
有关其他故障排除信息,请参阅类设计器错误。
什么是类设计器?