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)定义一个事件,实际上是在背后定义了一个委托类型的私有字段和三个函数:
                            1add_Click    
                            2remove_Click
                            3raise_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)         类型参数约束:
         ACLI 泛型采用“基类 + 接口”的方式来实现对类型参数的“显式约束”。
         BCLI 泛型不支持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<int100>^ stack = gcnew StackInfor<int100>();
                   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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值