Win10论坛

Win10正式版系统下载主题平板

重定义Modern UI,打造完美Windows全新体验

Windows10下载|安装|新手宝典|必备软件

搜索
查看: 2366|回复: 2

[教程] Windows Store Apps 开发手札 – 2(基本类型、字符串、类) [复制链接]

此人已被屏蔽

UID
479441
帖子
1481
PB币
4371
贡献
0
技术
29
活跃
267

7周年庆典勋章 活动参与先锋 I'm Windows Phone用户 远景技术达人 应用界 远景智多星 8周年庆典勋章

发表于 2012-12-18 09:29:28 |显示全部楼层
本帖最后由 satanness 于 2012-12-24 15:37 编辑

在Windows Store App中,微软决定启用新的C++库,C++/CX便被搬上了舞台。C++/CX与以前听到的C++ 0x/11和C++/CLR并不同。C++ 0x/11是目前最新的C++标准,而C++/CLR是为了让C++开发的东西能够在.Net下运行,即编译后托管于CLR,属于Managed C++。C++/CX属于本地语言(Native C++),没有垃圾回收等其他功能。
好,接下来抱怨一下这个C++/CX。 对于C++比较熟悉的人,都知道C++的学习过程,从C语言开始,然后是面向对象,然后是STL,其他标准库(多线程啊,输入输出啊,等等),说不定还要懂点C++的运行机制才能说自己懂这门语言。这个过程是微软一次次的更改C++的标准库造成的。如今又来了个C++/CX,实在让大家苦不堪言。 不要嫌我抱怨,国外的攻城狮们也都叫苦不迭。传送门里的这篇文章不仅是好文,下面的评论也叫人捧腹,看来微软写的这一笔,叫人开心不起来。
现在C++/CX资料还不算多,除了MSDN论坛上会有微软工程师们不定期地发篇帖子教导一下之外,就只有MSDN上有比较系统、全面的学习了。
废话说得够多了。 本文并不打算跟MSDN一样,系统、全面地介绍C++/CX,毕竟没有人家MSDN来的专业,只介绍一下C++/CX相对于传统C++有什么不同之处。 先从最基本的东西说起。

-基本类型-
基本类型C++/CX & C++对比

微软建议,为了使代码简单明了,建议改用 C++/CX 名称。当然,这么些年了,很多东西已经习惯了,要改可不简单。


布尔类型和字符类型C++/CX & C++对比

布尔类型变成了boolean(注意大小写),宽字符变成了char16,当然,要使用以前的名称也是可以的。
         

-字符串-       
字符串String在C++/CX中,属于Platform命名空间。在使用的时候,要加帽子符。String 对象的值是 char16(16 位 Unicode)字符的不可变(只读)序列。由于 String 对象是不可变的,因此将新字符串文本分配给 String 变量其实就是用新的 String 对象替换原始 String 对象。串联运算涉及析构原始 String 对象和创建新对象。跟char[n]数组原理一样,一旦赋值,便不可更改,除非用其他数值或方法替换(strcpy)。

字符串初始化
  1. // Initializing a String^ by using string literals
  2. String^ str1 = "Test"; // ok for ANSI text only. uses current code page
  3. String^ str2("Test");
  4. String^ str3 = L"Test";
  5. String^ str4(L"Test");

  6. //Initialize a String^ by using another String^
  7. String^ str6(str1);
  8. auto str7 = str2;

  9. // Initialize a String from wchar_t* and wstring
  10. wchar_t msg[] = L"Test";
  11. String^ str8 = ref new String(msg);
  12. std::wstring wstr1(L"Test");
  13. String^ str9 = ref new String(wstr1.c_str());
  14. String^ str10 = ref new String(wstr1.c_str(), wstr1.length());
复制代码
使用方法有直接初始化,用其他字符串对象初始化,或者用堆区空间初始化。第三种方法的ref new是啥意思先不管,下面会介绍之。

字符串操作
  1. // Concatenation
  2. auto str1 = "Hello" + " World";
  3. auto str2 = str1 + " from C++/CX!";   
  4. auto str3 = String::Concat(str2, " and the String class");

  5. // Comparison
  6. if (str1 == str2) { /* ... */ }
  7. if (str1->Equals(str2)) { /* ... */ }
  8. if (str1 != str2) { /* ... */ }
  9. if (str1 < str2 || str1 > str2) { /* ... */};
  10. int result = String::CompareOrdinal(str1, str2);

  11. if(str1 == nullptr) { /* ...*/};
  12. if(str1->IsEmpty()) { /* ...*/};

  13. // Accessing individual characters in a String^
  14. auto it = str1->Begin();
  15. char16 ch = it[0];
复制代码
字符串的操作方式也没啥变化。操作符如“+”“=”“>”“<”还是可以正常使用的。

字符串转换
  1. // Create a String^ variable statically or dynamically from a literal string.
  2. String^ str1 = "AAAAAAAA";

  3. // Use the value of str1 to create the ws1 wstring variable.
  4. std::wstring ws1( str1->Data() );
  5. // The value of ws1 is L"AAAAAAAA".

  6. // Manipulate the wstring value.
  7. std::wstring replacement( L"BBB" );
  8. ws1 = ws1.replace ( 1, 3, replacement );
  9. // The value of ws1 is L"ABBBAAAA".

  10. // Assign the modified wstring back to str1.
  11. str1 = ref new String( ws1.c_str() );
复制代码
字符串的转换也比较简单,多利用一下String类的内部成员函数就可以了。 如果代码接收字符串或字符串文本并仅将其传递给其他方法,则可使用Platform::StringReference^而不是 Platform::String^ 避免创建字符串数据的额外副本。在循环和要传递大量 String^ 实例的情况下,使用 StringReference^ 可提高性能。但目前MSDN上并没有StringReference^类的例子,后面找到相应的例子时再添加。

-枚举-       
枚举也有改变。C++/CX 支持 public enum class 关键字,该关键字类似于标准 C++ scoped enum。当使用通过 public enum class 关键字声明的枚举数时,必须使用枚举标识符确定每个枚举值的范围。
  1. // Define the enum
  2. public enum class TrafficLight : int { Red, Yellow, Green }; //…
复制代码
当然也可以像如下方式声明:
  1. public enum class Enum1
  2. {
  3.     None = 0,
  4.     First, // First == 1
  5.     Some = 5,
  6.     Many = 10
  7. };

  8. // Consume the enum:
  9. TrafficLight myLight = TrafficLight::Red;
  10. if (myLight == TrafficLight::Green)
  11. {
  12.     //...
  13. }
复制代码
可见用法跟以前也不太一样,已经将enum视为一个类了,此类成员权限默认为public。
         
-ref类和结构-              
类的变化算是重头戏。其实早在CLR里,就已经有ref类了,不过属于Managed C++,托管于CLR,所以“血统”不够“纯正”。这次C++的编译器也可以认识这个ref和帽子符“^”了。
      ref 类或 ref 结构具有以下基本功能:
      1. 它必须在一个命名空间内声明,并且它在该命名空间中可具有公共或私有可访问性。仅将公共类型发送到元数据。(有没有C#的感觉了?)
      2. 它可以作为成员 C++/CX 构造或标量类型(如枚举类、ref 类、float64 等)包含。它还可以包含标准 C++ 类型。C++/CX 构造可包含公共、受保护的、内部、私有或受保护的私有可访问性。公共或受保护的成员将发送到元数据。标准 C++ 类型必须具有私有、内部或受保护的私有可访问性,这可阻止将该类型发送到元数据(.winmd)。
      3. 它可实现一个或多个“接口类”或“接口结构”。(有没有Java的感觉了?)
      4. 它可从一个基类继承,并且基类自身具有附加限制。公共 ref 类层次结构的继承比私有 ref 类中的继承具有更多限制。
      5. 它不能声明为泛型。如果它具有私有可访问性,则可以为模板。其生存期由自动引用计数管理。(有没有objective c++的感觉了?)
      总的来说,这几种特性让人感觉C++的类已经不是类了,在吸取了几种语言的特性后,变成了一个四不像的生物。当然,这种变化也有好处,比如程序员可以更好地区分类传递是否是“引用传递”;引用计数可以减少内存泄漏;对于内部成员的可访问性有了更严格的规定等等。

类的声明
  1. namespace PersonaInfo
  2. {
  3.     [Windows::Foundation::Metadata::WebHostHiddenAttribute]
  4.     ref class Person
  5.     {
  6.     internal:
  7.         Person() {};
  8.         Person(Platform::String^ name);
  9.     public:
  10.         boolean SetPerson(Platform::String^ name, Platform::String^ phoneNumber);
  11.         virtual Platform::String^ SetAddress(Platform::String^ address) sealed;
  12.         Platform::String^ GetName() {return _name;}
  13.         Platform::String^ GetNumber() {return _phoneNumber;}
  14.     private:
  15.         Platform::String^ _name;
  16.         Platform::String^ _phoneNumber;
  17.     };
  18. }
复制代码
类的实现
  1. using namespace PersonaInfo;

  2. Person::Person(Platform::String^ name)
  3. {
  4.     _name = name;
  5.     _phoneNumber = "";
  6. }

  7. Person::~Person() { }

  8. boolean Person::SetPerson( Platform::String^ name, Platform::String^ phoneNumber )
  9. {
  10.     _name = name;
  11.     _phoneNumber = phoneNumber;
  12.     return TRUE;
  13. }
  14.   
  15. Platform::String^ PersonaInfo::Person::SetAddress( Platform::String^ address )
  16. {
  17.     return nullptr;
  18. }
复制代码
类的使用
  1. Person^ person1 = ref new Person("Pete");
  2. person1->SetPerson("Steadman", "110");
  3. Person^ person2 = person1; // Pointing to a same memory location
复制代码

类的继承
  1. ref class Student sealed: public Person
  2. {
  3. public:
  4.     Student() {};
  5.     virtual ~Student() {};
  6. };
复制代码

看完类的声明、实现及使用后,来详细讲讲变化。
1. 首先是namespace。在C++/CX中,所有的类应当属于某个命名空间,当然了,不加namespace也可以,但是在与页面文件.xaml交流时,没有命名空间可能会非常尴尬。
2. sealedseal有“封装、密封”之意,基本上有两种用法。
  1. class class-name sealed {...}                 // 表示该类不可做为基类被继承。
  2. virtual return-type Func() sealed {...}     // 表示该虚函数不可被重写。
复制代码
3. ref。在某个对象被声明为ref对象时,进行引用传递时,传递的是该对象的句柄而不是该对象本身。这就意味着,上述例子中,person1和person2指向的是同一个内存地址。
4. [Windows::Foundation::Metadata::WebHostHiddenAttribute] 这条语句是为了类的安全性着想的。在C++/CX中,它的名字叫做特性。特性是一类特殊的 ref 类,可在方括号中将其附加在 Windows 运行时类型和方法之前,以指定元数据创建中的某些行为。ref类可包含publicprotectedprivate成员,只有publicprotected成员会被发送到元数据,上文提到过。定义公共 ref类或结构时,编译器将必需的特性应用到类,并将该信息存储到应用程序的 .winmd 文件中。但是,当定义公共未密封的 ref 类时,应手动应用[Windows::Foundation::Metadata::WebHostHiddenAttribute]。该特性可确保该类对用 JavaScript 编写的 Windows Store App不可见。
5. 继承。 以下是适用于 C++/CX 中的继承的基本规则:
  • 虽然 ref 类最多从一个 ref 基类直接继承,但它可以实现任意数量的接口。
  • 如果类具有公共构造函数,则必须将其声明为密封类以防止进一步派生。
  •         您可创建具有内部或受保护的私有构造函数的公共未密封基类,前提是该基类从现有未密封基类(如Windows::UI::Xaml::DependencyObject)直接或间接派生。不支持跨 .winmd 文件继承用户定义的 ref 类;但是,ref 类可从其他 .winmd 文件中定义的接口继承。您只能从同一 Windows 运行时组件或 Windows 应用商店应用程序中的用户定义的 ref 基类创建派生类。
  • 对于 ref 类,仅支持公共继承。
              
先说这么多吧,下一篇再讲一下一些新的特性:属性、委托、事件。




Rank: 2Rank: 2

UID
721868
帖子
116
PB币
119
贡献
0
技术
0
活跃
34

应用界

发表于 2012-12-18 16:51:47 |显示全部楼层
谢谢分享,学习了呵呵
1

查看全部评分

Rank: 2Rank: 2

UID
560592
帖子
200
PB币
0
贡献
0
技术
0
活跃
176
发表于 2012-12-24 17:16:18 |显示全部楼层
谢谢分享,学习了.
回顶部
Copyright (C) 2005-2020 pcbeta.com, All rights reserved
Powered by Discuz!  苏ICP备17027154号
请勿发布违反中华人民共和国法律法规的言论,会员观点不代表远景论坛官方立场。
远景在线 | 远景论坛 | 苹果论坛 | Win10论坛 | Win8论坛 | Win7论坛 | WP论坛 | Office论坛 | 电脑硬件 | 安卓软件