在类设计器中使用 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 类实例化成各个单独的对象。 可能只打算从它派生其他类型的动物类,例如,PenguinWhaleFish。 在这种情况下,需要将 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;
}

在类图中显示此代码时,类图会绘制一条从 FishSwimmer 的继承线。

匿名类

类设计器支持匿名类 。 匿名类类型是指未使用标识符声明的类。 匿名类不能有构造函数或析构函数,不能作为自变量传递给函数,也不能作为返回值从函数返回。 匿名类可用于将类名替换为 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++ 枚举形状的外观和工作原理与结构形状类似,只不过其标签显示为 EnumEnum 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;

C++ class typedef in Class Designer

结构 typedef 示例

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

C++ struct typedef in Class Designer

未命名的 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++ 代码。

  • 类设计器不支持全局函数和变量 。

  • 类设计器不支持联合 。 这是一种特殊类型的类,在其中仅分配联合的最大数据成员所需的内存量。

  • 类设计器不显示基本数据类型,如 intchar

  • 类设计器不显示在当前项目外部定义的类型(如果此项目没有对这些类型的正确引用) 。

  • 类设计器可以显示嵌套类型,但不能显示嵌套类型与其他类型之间的关系 。

  • 类设计器无法显示 void 类型或从 void 类型派生的类型 。

类型解析和显示问题的疑难解答

源文件的位置

类设计器不会持续跟踪源文件的位置 。 因此,如果修改项目结构或移动项目中的源文件,则类设计器会失去对类型的跟踪(尤其是 typedef、基类或关联类型的源类型) 。 可能会收到错误,如“类设计器无法显示此类型” 。 如果收到错误,要将修改过的或被重新定位的源代码再次拖到类图中以重新显示。

更新和性能问题

对于 C++ 项目,在源文件中所做的更改要出现在类图中可能需要 30 到 60 秒的时间。 这种延迟也可能导致类设计器引发错误“选定内容中未找到任何类型” 。 如果收到此类错误,请在错误消息中单击“取消”,并等待代码元素出现在类视图中 。 之后,类设计器应该可以显示此类型 。

如果类图未使用你在代码中所做的更改进行更新,则可能需要关闭关系图,并重新打开它。

类型解析问题

以下原因可能会导致类设计器无法解析类型 :

  • 该类型所在的项目或程序集未从包含类图的项目进行引用。 若要纠正此错误,请添加一个对包含该类型的项目或程序集的引用。 有关详细信息,请参阅管理项目中的引用

  • 由于该类型未处于正确的范围内,因此类设计器无法找到它 。 确保代码未缺失 usingimports#include 语句。 还请确保未将该类型(或相关类型)移出它原来所在的命名空间。

  • 该类型不存在(或已被注释掉)。 若要更正此错误,请确保未注释掉或删除该类型。

  • 类型位于由 #import 指令引用的库中。 可行的解决方法是:手动将生成的代码(.tlh 文件)添加到头文件的 #include 指令中。

  • 确保类设计器支持你输入的类型 。 请参阅 C++ 码位元素的限制

最有可能看到的有关类型解析问题的错误是:无法在类图“<element>”中找到一个或多个形状的代码。 此错误消息不一定表示你的代码错误。 它仅指示选件类设计器无法显示你的代码。 你可以尝试以下方法:

  • 确保该类型存在。 确保你没有无意中注释掉或删除源代码。

  • 尝试解析的类型。 该类型所在的项目或程序集未从包含类图的项目进行引用。 若要纠正此错误,请添加一个对包含该类型的项目或程序集的引用。 有关详细信息,请参阅管理项目中的引用

  • 确保该类型位于正确的范围,因此选件类设计器可以找到它。 确保代码未缺失 usingimports#include 语句。 还请确保未将该类型(或相关类型)移出它原来所在的命名空间。

提示

有关其他故障排除信息,请参阅类设计器错误