C++数组 在c++中,数组的大小必须在编译时确定,并且将数组传递给函数时,传递的只是数组起始地址,所以要想办法连同数组大小一同传递给函数。
1 2 3 int arr[4 ] = { 1 ,2 ,3 ,4 };int arr1[] = { 1 ,2 ,3 ,4 };int arr2[2 ][3 ]
动态创建数组 C++中直接声明数组需要明确数组的大小,但是可以使用new来动态创建数组,虽然这样数组也有固定的大小,只是在运行期间可以确定需要多少元素后再创建制定大小数组。
1 2 int * pa = new int [size];delete [] pa;
C++/CLI泛型 C#中具有泛型类型,C++/CLI中也具有泛型类型。
1 2 3 4 5 6 7 8 9 10 generic <typename T> ref class Mylist { public : void Add (T obj ) ; T GetAtIndex (int idx ) ; }; Mylist<String^>^ lists = gcnew Mylist <String ^>() ;
C++中的泛型模板和.net中的泛型虽然功能很相似,但是工作方式完全不同,所以在C++/CLR中都得到了支持。两者主要的不同之处有:
模版是在编译时就实例化好的,而泛型是在运行时仍然是泛型的; 模版支持特化、非类型模板参数和模版参数等,而泛型不支持,要简单的多; 泛型类型不能从类型参数继承,而模板可以; 泛型不支持元编程; 泛型类型支持类型参数约束,模板不支持。 托管数组 与C++不同,托管数组直接分配到堆上,首gc的管理,而且索引不再制定从某个地址偏移。并且要用Array关键字来声明。
1 2 3 4 5 6 array<int >^ arr1; array<IntVal^, 2 >^ arr2; array<int >^ arr1 = gcnew array <int >(3 ) { 1 , 2 , 3 }; array<int >^ arr2 = gcnew array<int > {1 , 2 , 3 }; array<int >^ arr3 = {1 ,2 ,3 };
对于引用类型的数组,实际上是句柄的数组。例如main函数int main(array<System::String^>^ args)
,实际上是String的句柄数组。另外.net提供了for each循环来遍历数组,与C#一样任何实现了IEnumberator接口的集合都可以使用for each
1 2 3 4 5 6 array<int >^ arr3 = {1 ,2 ,3 }; for each (int s in arr3 ){ Console::WriteLine(s); }
多维数组 与C++不同,多维数组的维数要在尖括号中定义,且读取多维数组也要在一个方括号中添加索引。
1 2 3 4 5 6 7 8 9 10 array<int , 2 >^ array2d = gcnew array <int , 2>(3 , 3 ) ; array2d[1 , 2 ] = 3 ; array<int , 2 >^ array2d_1 = { {1 ,2 ,3 }, {4 ,5 ,6 }, {7 ,8 ,9 } }; Console::WriteLine(array2d_1[0 ,1 ]);
List<T>
在实际开发过程中,更多的使用泛型集合类,因为集合可以改变大小。
1 2 3 4 5 6 7 8 9 10 using namespace System ::Collections ::Generic ;List<int >^ lst = gcnew List <int >() ; lst->Add(0 ); lst->Add(1 ); lst->Add(2 ); List<int >^ lst = gcnew List <int >(10 ) ; SortedList<String^, int >^ sl = gcnew SortedList <String ^, int >() ; sl->Add("a" , 1044 );
STL/CLR STL容器是标准C++一部分,提供了一系列高性能、可扩展的集合类。C++/CLi提供了托管STL版本。使用方法与STL类似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <cliext/vector> using namespace System;using namespace cliext;int main (array<System::String^>^ args) { vector<double > v1; for (int i = 0 ; i < 10 ; i++) { v1.push_back (i * 2 ); } for (vector<double >::iterator it = v1.begin ();it!=v1.end (); it++) { Console::WriteLine (*it); } Console::WriteLine ("程序结束" ); }
属性 在.net中一般不会公开字段,而是公开属性。属性本身就是方法包含get和set。在C++/CLI中支持两种属性,标准量属性和索引属性。
标量属性 标量属性也就是最常见的属性,将私有字段使用属性保护起来,使用property
来声明,而且可以根据需要只实现get以满足只读属性的要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ref class Person { public : property String^ Name { String^ get () { return name; } void set (String^ value) { name = value; } } property int Age { int get () { return age; } void set (int value) { age = value; } } private : String^ name; int age; }; int main (array<System::String^>^ args) { Person^ p = gcnew Person (); p->Name = "小明" ; p->Age = 10 ; Console::WriteLine ("{0}今年{1}岁" , p->Name, p->Age); Console::WriteLine ("程序结束" ); }
自动属性 在C#中是可以自动实现属性的如public int Order { set; get; }
,C++/CLI中同样可以:property String^ Name
。
属性继承 因为属性本质上就是方法,所以可以实现虚属性,以达到重写属性的目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public ref class Shape abstract { public : virtual property double Area; }; public ref class Circle :Shape { private : double r=1 ; public : virtual property double Area { double get () override { return Math::PI * r * r; } } };
属性索引 属性索引就是可以在对象上直接使用[]
来访问,其工作方式与标量属性相似,只需要在属性名后面的方括中包含索引类型就可以
property double Name[int]
,这段代码定义的索引属性为Name,其索引类型为long,在get和set函数中的第一个参数必须为索引。
1 2 3 4 5 6 7 property double Name[int ] { double get (int idx ) {...} void set (int idx,double vlaue ) {...} } double bal = a1->Name[10 ];
如果使用defaut名称,可以在对象上直接访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ref class Account { private : List<int >^ lst = gcnew List <int >() ; public : Account() { lst->Add(1 ); lst->Add(2 ); lst->Add(3 ); lst->Add(4 ); lst->Add(5 ); lst->Add(6 ); } property int Value[int ] { int get (int idx ) { return lst[idx]; } } property int default [int ] { int get (int idx ) { return lst[idx]; } } }; int main (array<System::String^>^ args ){ Account^ a = gcnew Account () ; int s = a->Value[0 ]; int ss = a[1 ]; Console::WriteLine(s); Console::WriteLine(ss); Console::WriteLine("程序结束" ); }