C++:C++/CLI

       CLI 指的是通用语言结构,一种支持动态组件编程模型的多重结构,在许多情况下,这代表了一个与C++对象模型完全颠倒了的模式,一个时实的软件层,有效的执行了系统,在底层操作系统与程序之间运行,操作底层的设备受到一定限制,操作执行程序中的活动类型及与程序相关联的下部结构得到了支持,反斜杠(/) 代表C++和CLI的捆绑。

  C++/CLI : 它是静态C++对象模型到CLI的动态组件对象编程模型的捆绑,简而言之,它就是你如何用C++在.net中编程。

CLR实时通用语言是CLI的微软版本,它非常适用于Windows操作系统,相似地,Visual C++2005是C++/CLI的实现。

  作为第二个近似的答案,我认为C++/CLI是.NET编程模式与C++的结合,正如以前将模板与C++结合起来产生的泛型编程。所有这种结合中,企业所拥有的C++的投资以及开发人员使用C++的经验将得到保存,而这恰恰是使用C++/CLI进行开发的重要基础。

DOCUMENT

 

CLI对象模型
1 .追踪句柄             tracking handle
2 .内部指针                interior pointer
3 .固定指针                pinning pointer
 
追踪句柄 --- 指向“托管堆上一个完整的对象( whole object )”的指针。是会自动更新的指针
内部指针 --- 指向托管堆上“对象所包涵的内部成员” 的指针
固定指针 --- 固定托管堆上“对象所包含的数据成员的指针”,使之不能被垃圾收集器控制
 
2 .数据成员
1 )实例字段 :占据存储位置,表示组件 / 对象状态,不同对象的实例字段拥有不同的存储位置
2 )静态字段 :占据存储位置,表示组件 / 对象的全局状态,所有对象的静态字段“共享”同一个存储位置
3 )常量字段 :编译时常量,必须在声明的同时初始化(内联初始化),默认静态
4 )只读字段 :运行时只读,不可以改变,可以在声明的同时进行初始化(只对静态适用),或者在构造器中初始化,并不默认静态
3 .成员函数
1 )实例方法,属于对象实例,可以访问实例字段,也可以访问静态字段。
2 )静态方法,属于类型,不可访问实例字段,只能访问静态字段。
4 .组件成员 成员函数 + 数据成员的变体
1 )属性:函数变体,实际上是在背后生成了一个私有字段和两个公有的函数
2 )属性(扩展)
private : int Int_Data;
public : property int x
         {
                   int get()
                   {
                            return Int_Data;
                   }
                   void set(int value)
                   {
                            Int_Data = value;
                   }
         }
3 )事件
           1 )委托 – CLI 托管函数指针类型
              2 )定义一个事件,实际上是在背后定义了一个委托类型的私有字段和三个函数:
                            1 add_Click    
                            2 remove_Click
                            3 raise_Click
4 )事件扩展:
         public ref class Button
         {
                   EventHandler^ handler;
         public: event EventHandler^ Click
                   {
                            void add(EventHandler^ e)
                            {
                                     Lock<Mutex> I(m);
                                     handler += e;
                            }
                            void remove(EventHandler^ e)
                            {
                                     Lock<Mutex> I(m);
                                     handler -= e;
                            }
                   }
         };
 
托管编程与资源管理 :
           资源是软件的主题,使用资源总是难免的,但资源泄露总是可以避免的, C++/CLI 两大类资源,托管内存和非托管资源,托管内存是托管堆上的内存空间,非托管资源是本地堆内存,文件句柄,数据库连接,网络链接, GDI 设备句柄 ……
垃圾收集器只能追踪托管对象的内存使用,而无法知道费托管资源何时不再被使用,内存释放并不会导致非托管资源被释放。如何在内存被释放之前释放非托管资源
Object.Finalize 方法。 C++/CLI 不允许显式重写
ref class Destruction
{
protected : !Destruction()
         {
                  // 实际是在重写 System::Object.Finalize();
         }
};
Finalize 会将对象的代龄延长,使无效的对象长时间存在于托管堆中,给托管堆带来内存负担
Finalize 只会为托管资源清理提供了最后一层保障,并不推荐。
System::GC::SuppressFinalize(); 告知垃圾收集器不需要再调用 Finalize 从而减轻对象的负担
 
元数据与动态编程
C++/CLI 元数据系统
(1)         动态编程 1 ---- 反射  Reflection
(2)         动态编程 2 ---- 特性 Attributes          
动态程序是指能够在运行时改变自身结构和行为的程序
静态 ---- 编译时,早约束,紧耦合
动态 ---- 运行时,迟约束,松耦合         
ISO-C++ 是一门静态编程语言,只具有非常有限的动态能力,动态堆内存 ---- 虚函数的动态绑定,有限的类型识别能力 ----RTTI ,获得了极高的效率,却丧失了动态编程所具有的高灵活性
         --DLL 动态链接库
         --COM 组件          
反射 Reflection 动态的发现类型,操作类型,创建类型(查询元数据)
特性 Attributes 允许程序定义新的数据类型,从而在运行时动态的感知环境(创建元数据)         
元数据( Metadata ) : 是数据的数据,是 CLI 组件合同的描述载体,组件的平台的粘合剂, CLI                 元数据分为:定义型元数据 描述代码中定义了什么,引用型元数据 描述代码中引   用了什么,特性 扩展定义新的元数据。
 
泛型编程: 通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程模式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。它意味着一种新的抽象性质,从本质上来讲,它是数据类型的一组需求条件。泛型编程不是容器编程
 
C++/CLI 支持两大泛型机制,三种泛型应用
1 )编译时机制 ---- ISO-C++ 模版
                   ---- 编译时实例化
                   ---- 基于签名的隐式约束
2 )运行时泛型 ---- CLI 泛型
                   ---- 运行时实例化
                   ---- 基于“基类 + 接口”的显式约束。
应用:
(1)         ISO-C++ 本地类型上应用模板(编译时泛型)
(2)         CLI 托管类型上应用模板(编译时泛型)
(3)         CLI 托管类型上应用 CLI 泛型。
(4)        C++/CLI 所支持的泛型程序库
(1)         标准模板库 STL
(2)         CLI 标准模板库 STL.NET
(3)         CLI 泛型库 System::Collections::Generic
eg:
         generic <typename T>
         public ref class Stack
         {
         public: T tem;
                            T Pop()
                            {
                                     return tem;
                            }
                            String^ GetStr()
                            {
                                     // 用追踪句柄来调用函数成员
                                     return tem->ToString();
                            }
                            void Push(T t)
                            {}
                            int Size()
                            {
                                     return 0;
                            };
         };
         public: void TestEvery()
                   {
                            Stack<System::String^>^ sta = gcnew                                                 Stack<System::String^>();
         }
CLI 泛型机制:
第一轮编译时,编译器只为 Stack<T> 类型产生泛型版的 IL 代码与元数据 ---- 并进行泛型类型的实例化, T 在中间只充当占位符。
JIT 编译时,当 JIT 编译器第一次遇到 Stack<System::String^> 时,将 String^ 替换“泛型版” IL 代码与元数据中的 T---- 进行泛型类型的实例化。
CLI 为所有类型参数为 ref class 的泛型类型产生同一份代码,但是如果参数类型为 value class ,针对每一个不同的 value class CLI 将产生一份独立的代码。
CLI 泛型机制特点
(1)         由于 CLI 泛型的实例化会推迟到 JIT 编译阶段进行,因此未经实例化的泛型类型会存在于编译生成的程序集中,成为一个类型实体。
(2)         如果实例化泛型类型的参数相同,那么 JIT 编译器会重复使用该类型,因此 CLI 泛型可以避免 C++ 模板可能导致的代码膨胀问题。
(3)         CLI 泛型类型携带有丰富的元数据,因此可以通过反射来获取程序集中的泛型类型的相关信息。
CLI 泛型适用于四种对象:
(1)         CLI 托管类型 (包括引用类型和值类型)
(2)         CLI 接口类型
(3)         CLI 委托类型
(4)         函数 (成员函数,全局函数)
CLI 不适用于:
(1)         ISO-C++ 本地类型 ---- 本地类型没有 CLI 泛型的条件 :元数据的信息
(2)         CLI 属性,事件,索引器,操作符
A.                 CLI 泛型接口
         generic <typename Item>
         public interface class IList
         {
                   void ListCount();
         };
         generic <typename Item>
         ref class MyList : public IList<Item>
         {
         public: virtual void ListCount()
                  {
                            Console::WriteLine("Call interface method !");
                   }
};
B.                 CLI 泛型委托
         //delegate
         generic <typename type>
         public delegate void MyDelegate(type ty);
 
         public ref struct MyDeleClass
         {
         public ref class DeleClass
         {
         public: static void GetInt(int i)
                   {
                            Console::WriteLine("i is ");
                   }
         public: void UserDele()
                   {
                            MyDelegate<int>^ dele = gcnew MyDelegate<int>(&DeleClass::GetInt);
                            dele(200);
                   }
};                           
C.                 CLI 泛型函数
              ref class Megedata
        {              
                generic <typename T>
                void ControType(T t)
                {
                }
        };
        调用泛型函数:
              Megedata^ mana = gcnew Megedata();
         mana->ControType<int>(2);
泛型约束
(1)         类型参数约束:
         A CLI 泛型采用“基类 + 接口”的方式来实现对类型参数的“显式约束”。
         B CLI 泛型不支持 ISO-C++ 模板所使用的基于“签名”的“隐式约束”。
         C .虽然获得了编译时类型安全和相关代码清晰,但却丧失了很多灵活性(无法使用静态函数,操         作符、字符、内嵌类型等)
2 ) 结束代码示例
         generic <typename T>
         ref class MyCollect
         {
                  T t;
                  public void Add()
                  {};
         };
         T 实现 IComparable 接口
 CLI 泛型与 C++ 模板:
         两个根本性的区别:
(1)         C++ 模板为编译时实例化, CLI 泛型为运行时实例化
(2)         C++ 模板为基于“签名”的隐式约束, CLI 泛型为基于“基类 + 接口”的显式约束。
CLI 泛型不支持如下 C++ 模板中的机制:
(1)         非参数类型
(2)         缺省参数值
(3)         模板的模板参数
(4)         模板特化及部分特化。
A 非参数类型
                  template <class type,int size>
                  public ref class StackInfor
                  {
                           array <type>^ m_stack;
                           int top;
                  public : StackInfor() : top(0)
                            {
                                     m_stack = gcnew array<type>(size);
                            }
                  };
                  // 调用 StackInfor
                  StackInfor<int,100>^ stack = gcnew StackInfor<int,100>();
                   B .缺省参数值
                  template <class type,int size = 256 >
                   public ref class StackInfor
                   {
                            array <type>^ m_stack;
                            int top;
                   public : StackInfor() : top(0)
                            {
                                     m_stack = gcnew array<type>(size);
                            }
                   };
                   // 调用 StackInfor
                   StackInfor<int>^ stack = gcnew StackInfor<int>();
                   StackInfor<int 100 >^ stack = gcnew StackInfor<int 100 >();
                   C .模板的模板参数
                   template <template<class T>class TT,class t>
                   ref class MyClass
                   {
                            TT<t> m_data;
                   };
 
                   template <class t>
                   public ref class Apple
                   {};
 
                   ref class Use
                   {
                   public : void Test()
                            {
                                     MyClass<Apple,int> ^m_clas = gcnew MyClass<Apple,int>();
                            }
                   };
                   D .模板的局部特化
                   //-----------
                   template <long B,long E>
                   ref struct Power
                   {
                            literal long value = B * Power<B,E-1>::value;
                   };
                   template <long B>
                   ref struct Power<B,0>
                   {
                            literal long value = 1;
                   };
                   // 调用
                   Console::Write(Power<2,10>::value);

你可能感兴趣的:(C++:C++/CLI)