| 订阅 | 在线投稿
分享
 
 
当前位置: 王朝网络 >> c/c++ >> 使用Rational进行C++转换的技巧
 

使用Rational进行C++转换的技巧

2008-06-01 02:10:21 编辑來源:互联网 繁體版 评论
 
 
  UML 是一个通用的语言。使用 IBM? Rational Software Architect 和 IBM Rational Systems Developer,您可以实现由 UML 模型向 C++ 的转换。这篇文章讨论了如何更好地控制由 UML 向 C++ 转换而生成的 C++ 代码。文章分成几个章节,各部分相对独立,分别介绍了一种技巧。您可以根据需要选读,而不必遵循特定的次序。

  应用 C++ Transformation 概要文件以实现 C++ 结构的建模

  在统一建模语言 UML 和某特定领域之间建立联系的标准方法是使用 UML PRofile(UML 概要文件)。UML 概要文件可以为已有 UML 元素定义附加语义和特性,例如类、操作等。建模 C++ 特定元素的时候,如 结构体、联合体、名字空间 等,需要用到 UML 概要文件。在 Rational Software Architect 和 Rational Systems Developer 使用 C++ Transformation profile 实现 UML 向 C++ 的转换,这个概要文件在 UML 模型中的应用如下所示。

  在 Project EXPlorer 中选择概要文件将要应用的 UML 模型。

  在 Project Explorer 保持模型是选中状态,转换到 Properties View,单击 Profiles 选项卡。

  如图1所示,单击 Add Profile 按钮。

  图1. 将 UML 运用到 C++ Transformation 概要文件

使用Rational进行C++转换的技巧


  如图2所示,从 Deployed Profile 下拉列表框中选择 C++ Transformation。

  图2. 选择 C++ Transformation

使用Rational进行C++转换的技巧


  导入 C++ 类型库

  UML 提供了一组已定义好的类型,有 Boolean, Integer, String 和 UnlimitedNatural。而大多数的编程语言,包括C++,提供了更为丰富的基本类型。在 C++ 中建模的时候,您可能经常需要使用 C++ 预定义的原始类型(比如,将一个类型赋给某个属性、参数、操作返回类型,等)。To import the C++ model library that is shipped with the C++ Transform,在 Project Explorer 中右键单击UML模型,然后选择 Import Model Library,如下图3所示。

  图3. 导入 C++ 类型库

使用Rational进行C++转换的技巧


  如图4所示,从 Deployed Library 列表中选择 C++ Types。

  图4. 导入 C++ Type Library

使用Rational进行C++转换的技巧


  在模型中创建 C++ 名字空间

  本章节讲述如何在 UML 模型中为 C++ 名字空间建模。在 C++ 中创建一个名字空间时,需要将 cpp_namespace 原型应用在 UML 包。在 UML 向 C++ 转换的过程中,一个 UML 包默认被映射成一个文件夹。假如想要将 UML 包映射成名字空间,而不是文件夹,那么,您需要应用 cpp_namespace 原型,然后设置 NamespaceName 的属性,使其与指定的名字空间相关联。这个 stereotyped UML 包下所有的 类、结构、枚举 (以及其它)生成代码之后,都将包括在这个名字空间中。

  您可能想知道为什么名字空间不能直接采用 stereotyped 包的名称。这是为了支持 C++ 匿名的名字空间建模。所以,假如您将 NamespaceName 属性设置为空,那么,该名字空间就会被认为是匿名的。

  建模 C++ typedefs

  要建模 C++ typedef,需要创建一个 UML 类并在其上应用 cpp_typdef 原型。该原型提供了以下属性/值:

  arrayDimensions

  ImplementationType

  qualifier

  想要创建一个类型定义,比如 typedef int const IntMatrix100_20_t [10][20];,首先创建一个 UML 类 IntMatrix100_20_t,然后应用 cpp_typedef 原型。如图5所示,设置该原型的属性。

  图5. 建立一个 C++ 类型定义

使用Rational进行C++转换的技巧


  在将 typedef 定义与概要文件中提供的属性相关联的过程中,您可能会考虑到以下方式: typedef

  创建多维数组属性

  在本节中,您将会学到如何为一个大小为[10][20][30]的三维数组定义属性。在 Project Explorer 中选择需要赋给多维数组的属性。在 Properties 视图中,单击 Stereotypes 选项卡,然后单击 Apply Stereotypes 按钮,并选择 cpp_type 原型。这个原型提供了以下属性/值:

  arrayDimensions

  InitializerKind

  isAuto

  isMutable

  isRegister

  isVolatile

  qualifier

  如图6所示,在 arrayDimensions Value 处,指定 [10][20][30]。这样,在源代码中就会生成维度属性为[10][20][30]的数组。

  图6. 设置 Multidimensional Attributes

  将一个方法的形参设置为常量

  这个技巧的原理同上(前面提到的定义多维数组)。在 Project Explorer 中选择预备设置为 const 的参数。单击 Apply Stereotypes 按钮并选择 cpp_type 原型。该类型提供了以下属性/值:

  arrayDimensions

  InitializerKind

  isAuto

  isMutable

  isRegister

  isVolatile

  qualifier

  这些属性都是可能用得到的,但暂时只介绍 qualifier 属性。在 qualifier 的 Value 处,输入 const (如 图5 所示)。这样,当转换执行的时候,将在源代码中为选定的参数生成带有常量修饰符的函数签名。

  注: 请确保输入的值是有效的。假如输入错误,则会导致编译失败,您需要在再次运行转换之前修正错误。

  另外,cpp_type 原型也适用于类的属性。但是,生成一个常量属性的更简单的方法是将属性标明为 Read Only。

  将整个方法声明为常量

  假设您想要将一个方法声明为常量,以便在生成的代码中带有 const 要害字: )int Operation1(MyType Parameter1 const;。您需要在 Properties 视图的 General 选项卡中选择 Query 修饰符。这里,不需要应用原型。

  图7. 创建一个常量方法

使用Rational进行C++转换的技巧


  给一个方法增加异常处理

  Exceptions 是 UML 中重要的类,它在建模过程中不需要使用概要文件。为了简化并推广建模, UML to C++ Transformation 使用了普遍适用的 UML 属性,而不是概要文件。要生成一个 throw 子句,比如 int Operation1() throw ( MyType);,您首先需要为操作创建一个参数,然后设置其 Is Exception 属性为 true。

  在转换过程中,参数名是可以被忽略的,但最好还是定义一个合适的名称(以备异常抛出时正确提示)。图8显示了如何将参数的 Is Exception 属性设置为 true。

  图8. 设置某方法的 throw 类型

使用Rational进行C++转换的技巧


  控制生成的代码中的 include 声明

  UML to C++ Transformation 可以自动生成恰当的 include 声明。 然而,您可能想要根据需要生成更合适的 include 声明。例如,已确定要使用本地方法体的某个类型变量,因此,想要生成包括在文件中的 include 声明建模时,您可能需要创建两个类之间的依靠,然后将 cpp_dependency 原型应用在依靠。这个原型和名为 IsInclusionInHeader 的属性一起出现,该属性值默认为 false。假如需要将 include 声明包括在生成的文件体中,请将这个属性值设为 false;假如需要将 include 声明生成在头文件中,那么,可以不设置依靠的 cpp_dependency 原型,也可以应用原型并将 IsInclusionInHeader 属性值设为 true。

  使用文件级别得重用保护部分

  假如要使用标准库的类型,或者一些源代码的其它库,您需要在模型中将这些类型设置为普通的字符串。例如,假如要将一个属性声明为整型,您需要在模型中指定它的类型为 vector 转换时,将会把这些类型当成原始类型,并且不会生成任何 include 声明或其它声明。因此,您需要将这些都明确地包含进源文件中。

  比如,对于 vector 类型,您应当明确地将 include 声明放置在源代码中,比如 #include 。如列表1所示,在应用 UML 向 C++ 的转换过程中,每个生成的文件都一字不漏地包含一些段落的内容。请注重 //TODO: Add definitions that you want preserved。您添加到 Begin section 和 End section 中的任何内容都将被保存下来。请在此处添加声明,比如这里的 #include 。

  列表1. 类 Car 所生成代码

  

  #ifndef CLASS1_H

  #define CLASS1_H

  //Begin section for file Class1.h

  //TODO: Add definitions that you want preserved

  //End section for file Class1.h

  #include "MyType.h"

  //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"

  class Class1

  {

  //Begin section for Class1

  //TODO: Add attributes that you want preserved

  //End section for Class1

  public:

  //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"

  int Operation1()const throw ( MyType);

  }; //end Class Class1

  #endif

  删除类级别得重用保护部分

  请注重,在前面列表1的代码中,有一段 //Begin section for Class1 ... //End section for Class1 ,您可以将 C++ 中所有不能建模的声明保存在这里。返回 UML to C++ Transformation 时,不会覆盖这段声明。假如您不需要这一声明出现在生成的代码中,可以选择删除。但是,删除之后,即使再次运行 UML to C++ Transformation,这些声明也不会重新生成。

  假如不需要,可以删除如列表2所示的段落,那么删除之后不能够重新生成。假使想要恢复这些声明,您就需要手动地进行插入。

  列表2. 类 Car 生成的代码

  

  ...

  //Begin section for Class1

  //TODO: Add attributes that you want preserved

  //End section for Class1

  ...

  不修改 UML 模型的情况下,改变生成包的名称。

  要改变包的名称,请双击打开转换配置文件。如图9所示,单击 Mapping 选项卡,选择 Enable mapping。

  图9. 使用映射模型

使用Rational进行C++转换的技巧


  单击 New 按钮,创建一个默认的映射模型,赋给一个适合的名称。单击 Edit Mapping 按钮,出现如图10所示的对话框。

  图10. 编辑映射模型

使用Rational进行C++转换的技巧


  假使您正进行到如图11所示的 UML 模型。假如没有映射模型,那么 Date 类将会生成在一个名为 Package1 的文件夹内。然而,假如您想要将 Package1 生成为 Folder1,那么需要使用映射模型。浏览映射模型,找到 Package1,然后在向导底端的 Mapped Name 编辑框输入 Folder1。这样,在生成的代码中,Date 类就生成在名为 Folder1 的文件夹内了。

  图11. 您正在操作的 UML 模型

  在同一个文件里生成多个类

  在映射模型中,假如您想将一个 UML 类映射为另外的名称,您需要改变其将要生成文件的名称,而不是类名。默认情况下,顶级类将生成一个与类名相同名称的文件。因此,对于一个名为 MyClass 的 UML 类,UML 向 C++ 的转换将会生成文件 MyClass.h 和 MyClass.cpp。

  但是,在使用映射模型的时候,您也可以选择生成与原类名不同名称的文件。比如,您可以改变 UML 包的名称,生成另外命名的文件夹;您也可以将一个 UML 类映射为另外命名的文件。类的名称并不受映射模型的影响。因此,要想在一个文件中生成多个类,您所需要做的仅仅是在映射模型中为它们指定相同的目标名称。
 
 
 
上一篇《C++ builder 的文件读写操作总结》
下一篇《Win32下两种用于C++的线程同步类(上)》
 
 
 
 
 
 
日版宠物情人插曲《Winding Road》歌词

日版宠物情人2017的插曲,很带节奏感,日语的,女生唱的。 最后听见是在第8集的时候女主手割伤了,然后男主用嘴帮她吸了一下,插曲就出来了。 歌手:Def...

兄弟共妻,我成了他们夜里的美食

老钟家的两个儿子很特别,就是跟其他的人不太一样,魔一般的执着。兄弟俩都到了要结婚的年龄了,不管自家老爹怎么磨破嘴皮子,兄弟俩说不娶就不娶,老父母为兄弟两操碎了心...

如何磨出破洞牛仔裤?牛仔裤怎么剪破洞?

把牛仔裤磨出有线的破洞 1、具体工具就是磨脚石,下面垫一个硬物,然后用磨脚石一直磨一直磨,到把那块磨薄了,用手撕开就好了。出来的洞啊很自然的。需要猫须的话调几...

我就是扫描下图得到了敬业福和爱国福

先来看下敬业福和爱国福 今年春节,支付宝再次推出了“五福红包”活动,表示要“把欠大家的敬业福都还给大家”。 今天该活动正式启动,和去年一样,需要收集“五福”...

冰箱异味产生的原因和臭味去除的方法

有时候我们打开冰箱就会闻到一股异味,冰箱里的这种异味是因为一些物质发出的气味的混合体,闻起来让人恶心。 产生这些异味的主要原因有以下几点。 1、很多人有这种习...

 
 
 
  UML 是一个通用的语言。使用 IBM? Rational Software Architect 和 IBM Rational Systems Developer,您可以实现由 UML 模型向 C++ 的转换。这篇文章讨论了如何更好地控制由 UML 向 C++ 转换而生成的 C++ 代码。文章分成几个章节,各部分相对独立,分别介绍了一种技巧。您可以根据需要选读,而不必遵循特定的次序。   应用 C++ Transformation 概要文件以实现 C++ 结构的建模   在统一建模语言 UML 和某特定领域之间建立联系的标准方法是使用 UML PRofile(UML 概要文件)。UML 概要文件可以为已有 UML 元素定义附加语义和特性,例如类、操作等。建模 C++ 特定元素的时候,如 结构体、联合体、名字空间 等,需要用到 UML 概要文件。在 Rational Software Architect 和 Rational Systems Developer 使用 C++ Transformation profile 实现 UML 向 C++ 的转换,这个概要文件在 UML 模型中的应用如下所示。   在 Project EXPlorer 中选择概要文件将要应用的 UML 模型。   在 Project Explorer 保持模型是选中状态,转换到 Properties View,单击 Profiles 选项卡。   如图1所示,单击 Add Profile 按钮。   图1. 将 UML 运用到 C++ Transformation 概要文件   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423204311.gif[/img][/url]   如图2所示,从 Deployed Profile 下拉列表框中选择 C++ Transformation。   图2. 选择 C++ Transformation   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423219496.gif[/img][/url]   导入 C++ 类型库   UML 提供了一组已定义好的类型,有 Boolean, Integer, String 和 UnlimitedNatural。而大多数的编程语言,包括C++,提供了更为丰富的基本类型。在 C++ 中建模的时候,您可能经常需要使用 C++ 预定义的原始类型(比如,将一个类型赋给某个属性、参数、操作返回类型,等)。To import the C++ model library that is shipped with the C++ Transform,在 Project Explorer 中右键单击UML模型,然后选择 Import Model Library,如下图3所示。   图3. 导入 C++ 类型库   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423219817.gif[/img][/url]   如图4所示,从 Deployed Library 列表中选择 C++ Types。   图4. 导入 C++ Type Library   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423219947.gif[/img][/url]   在模型中创建 C++ 名字空间   本章节讲述如何在 UML 模型中为 C++ 名字空间建模。在 C++ 中创建一个名字空间时,需要将 cpp_namespace 原型应用在 UML 包。在 UML 向 C++ 转换的过程中,一个 UML 包默认被映射成一个文件夹。假如想要将 UML 包映射成名字空间,而不是文件夹,那么,您需要应用 cpp_namespace 原型,然后设置 NamespaceName 的属性,使其与指定的名字空间相关联。这个 stereotyped UML 包下所有的 类、结构、枚举 (以及其它)生成代码之后,都将包括在这个名字空间中。   您可能想知道为什么名字空间不能直接采用 stereotyped 包的名称。这是为了支持 C++ 匿名的名字空间建模。所以,假如您将 NamespaceName 属性设置为空,那么,该名字空间就会被认为是匿名的。   建模 C++ typedefs   要建模 C++ typedef,需要创建一个 UML 类并在其上应用 cpp_typdef 原型。该原型提供了以下属性/值:   arrayDimensions   ImplementationType   qualifier   想要创建一个类型定义,比如 typedef int const IntMatrix100_20_t [10][20];,首先创建一个 UML 类 IntMatrix100_20_t,然后应用 cpp_typedef 原型。如图5所示,设置该原型的属性。   图5. 建立一个 C++ 类型定义   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423220055.gif[/img][/url]   在将 typedef 定义与概要文件中提供的属性相关联的过程中,您可能会考虑到以下方式: typedef   创建多维数组属性   在本节中,您将会学到如何为一个大小为[10][20][30]的三维数组定义属性。在 Project Explorer 中选择需要赋给多维数组的属性。在 Properties 视图中,单击 Stereotypes 选项卡,然后单击 Apply Stereotypes 按钮,并选择 cpp_type 原型。这个原型提供了以下属性/值:   arrayDimensions   InitializerKind   isAuto   isMutable   isRegister   isVolatile   qualifier   如图6所示,在 arrayDimensions Value 处,指定 [10][20][30]。这样,在源代码中就会生成维度属性为[10][20][30]的数组。   图6. 设置 Multidimensional Attributes      将一个方法的形参设置为常量   这个技巧的原理同上(前面提到的定义多维数组)。在 Project Explorer 中选择预备设置为 const 的参数。单击 Apply Stereotypes 按钮并选择 cpp_type 原型。该类型提供了以下属性/值:   arrayDimensions   InitializerKind   isAuto   isMutable   isRegister   isVolatile   qualifier   这些属性都是可能用得到的,但暂时只介绍 qualifier 属性。在 qualifier 的 Value 处,输入 const (如 图5 所示)。这样,当转换执行的时候,将在源代码中为选定的参数生成带有常量修饰符的函数签名。   注: 请确保输入的值是有效的。假如输入错误,则会导致编译失败,您需要在再次运行转换之前修正错误。   另外,cpp_type 原型也适用于类的属性。但是,生成一个常量属性的更简单的方法是将属性标明为 Read Only。   将整个方法声明为常量   假设您想要将一个方法声明为常量,以便在生成的代码中带有 const 要害字: )int Operation1(MyType Parameter1 const;。您需要在 Properties 视图的 General 选项卡中选择 Query 修饰符。这里,不需要应用原型。   图7. 创建一个常量方法   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423220359.gif[/img][/url]   给一个方法增加异常处理   Exceptions 是 UML 中重要的类,它在建模过程中不需要使用概要文件。为了简化并推广建模, UML to C++ Transformation 使用了普遍适用的 UML 属性,而不是概要文件。要生成一个 throw 子句,比如 int Operation1() throw ( MyType);,您首先需要为操作创建一个参数,然后设置其 Is Exception 属性为 true。   在转换过程中,参数名是可以被忽略的,但最好还是定义一个合适的名称(以备异常抛出时正确提示)。图8显示了如何将参数的 Is Exception 属性设置为 true。   图8. 设置某方法的 throw 类型   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423220426.gif[/img][/url]   控制生成的代码中的 include 声明   UML to C++ Transformation 可以自动生成恰当的 include 声明。 然而,您可能想要根据需要生成更合适的 include 声明。例如,已确定要使用本地方法体的某个类型变量,因此,想要生成包括在文件中的 include 声明建模时,您可能需要创建两个类之间的依靠,然后将 cpp_dependency 原型应用在依靠。这个原型和名为 IsInclusionInHeader 的属性一起出现,该属性值默认为 false。假如需要将 include 声明包括在生成的文件体中,请将这个属性值设为 false;假如需要将 include 声明生成在头文件中,那么,可以不设置依靠的 cpp_dependency 原型,也可以应用原型并将 IsInclusionInHeader 属性值设为 true。   使用文件级别得重用保护部分   假如要使用标准库的类型,或者一些源代码的其它库,您需要在模型中将这些类型设置为普通的字符串。例如,假如要将一个属性声明为整型,您需要在模型中指定它的类型为 vector 转换时,将会把这些类型当成原始类型,并且不会生成任何 include 声明或其它声明。因此,您需要将这些都明确地包含进源文件中。   比如,对于 vector 类型,您应当明确地将 include 声明放置在源代码中,比如 #include 。如列表1所示,在应用 UML 向 C++ 的转换过程中,每个生成的文件都一字不漏地包含一些段落的内容。请注重 //TODO: Add definitions that you want preserved。您添加到 Begin section 和 End section 中的任何内容都将被保存下来。请在此处添加声明,比如这里的 #include 。   列表1. 类 Car 所生成代码   #ifndef CLASS1_H   #define CLASS1_H   //Begin section for file Class1.h   //TODO: Add definitions that you want preserved   //End section for file Class1.h   #include "MyType.h"   //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"   class Class1   {   //Begin section for Class1   //TODO: Add attributes that you want preserved   //End section for Class1   public:   //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"   int Operation1()const throw ( MyType);   }; //end Class Class1   #endif   删除类级别得重用保护部分   请注重,在前面列表1的代码中,有一段 //Begin section for Class1 ... //End section for Class1 ,您可以将 C++ 中所有不能建模的声明保存在这里。返回 UML to C++ Transformation 时,不会覆盖这段声明。假如您不需要这一声明出现在生成的代码中,可以选择删除。但是,删除之后,即使再次运行 UML to C++ Transformation,这些声明也不会重新生成。   假如不需要,可以删除如列表2所示的段落,那么删除之后不能够重新生成。假使想要恢复这些声明,您就需要手动地进行插入。   列表2. 类 Car 生成的代码   ...   //Begin section for Class1   //TODO: Add attributes that you want preserved   //End section for Class1   ...   不修改 UML 模型的情况下,改变生成包的名称。   要改变包的名称,请双击打开转换配置文件。如图9所示,单击 Mapping 选项卡,选择 Enable mapping。   图9. 使用映射模型   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423220536.gif[/img][/url]   单击 New 按钮,创建一个默认的映射模型,赋给一个适合的名称。单击 Edit Mapping 按钮,出现如图10所示的对话框。   图10. 编辑映射模型   [url=http://www.wangchao.net.cn/bbsdetail_1785447.html][img]http://image.wangchao.net.cn/it/1323423220617.gif[/img][/url]   假使您正进行到如图11所示的 UML 模型。假如没有映射模型,那么 Date 类将会生成在一个名为 Package1 的文件夹内。然而,假如您想要将 Package1 生成为 Folder1,那么需要使用映射模型。浏览映射模型,找到 Package1,然后在向导底端的 Mapped Name 编辑框输入 Folder1。这样,在生成的代码中,Date 类就生成在名为 Folder1 的文件夹内了。   图11. 您正在操作的 UML 模型   在同一个文件里生成多个类   在映射模型中,假如您想将一个 UML 类映射为另外的名称,您需要改变其将要生成文件的名称,而不是类名。默认情况下,顶级类将生成一个与类名相同名称的文件。因此,对于一个名为 MyClass 的 UML 类,UML 向 C++ 的转换将会生成文件 MyClass.h 和 MyClass.cpp。   但是,在使用映射模型的时候,您也可以选择生成与原类名不同名称的文件。比如,您可以改变 UML 包的名称,生成另外命名的文件夹;您也可以将一个 UML 类映射为另外命名的文件。类的名称并不受映射模型的影响。因此,要想在一个文件中生成多个类,您所需要做的仅仅是在映射模型中为它们指定相同的目标名称。
󰈣󰈤
 
 
 
  免责声明:本文仅代表作者个人观点,与王朝网络无关。王朝网络登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
桌球宝贝_性感在蔓延(3)
桌球宝贝_性感在蔓延(2)
银杏树下清纯女孩(9)
银杏树下清纯女孩(8)
痞子的甘南日记
疑是银河落九天
雪域坝上四——纯美色
冬日恋歌——西城杨柳弄轻柔
 
>>返回首页<<
 
 
 为你推荐
 
 
 
 转载本文
 UBB代码 HTML代码
复制到剪贴板...
 
 热帖排行
 
 
 
 
©2005- 王朝网络 版权所有