clr包装c++让c#调用,委托如何转成c++的函数指针

shionco 2018-03-07 12:34:38
使用clr包装c++的sdk来让c#使用,sdk里的回调是函数指针,想通过clr包装,c#用委托

// core.h
namespace Core {
public ref class Live
{
public:
delegate void SucDelegateCallBack(void* data);
void init(SucDelegateCallBack^ suc);
};
}


// core.cpp
namespace Core {
void Live::init(SucDelegateCallBack^ suc) {
// sdk的头文件相关内容:
// typedef void (*SucCallback)(void* data);
// virtual void init(SucCallback suc = NULL) = 0;

// 想实现下面的想法,但是不知道如何将suc转成SucCallback
GetCore()->init(SucDelegateCallBack); //这里是错误的:参数类型不对
}
}


如何将SucDelegateCallBack转化成SucCallback呢?
...全文
483 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
扑克子 2020-02-21
  • 打赏
  • 举报
回复
谢谢,学到了简单的调用委托方法
shionco 2018-03-07
  • 打赏
  • 举报
回复
已解决! IntPtr ip = Marshal::GetFunctionPointerForDelegate(suc); SucCallback cb = static_cast<SucCallback>(ip.ToPointer());
c#学习笔记(1) 51099在线学习网发布 文章来源:网络收集 发布时间:2006-05-25 字体: [大 中 小] 51099在线学习网 http://www.51099.com 1, 结构(struct) 与 类(class) [attributes] [modifiers] struct identifier [:interfaces] body [;] 结构与类很相似,都表示可以包含数据成员和函数成员的数据结构。与类不同的是,结构是值类型并且不需要堆分配。结构类型的变量直接包含结构的数据,而类类型的变量包含对数据的引用(该变量称为对象)。 struct 类型适合表示如点、矩形和颜色这样的轻量对象。尽管可能将一个点表示为类,但结构在某些方案中更有效。在一些情况下,结构的成本较低。例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。结构可以声明构造函数,但它们必须带参数。声明结构的默认(无参数)构造函数是错误的。总是提供默认构造函数以将结构成员初始化为它们的默认值。在结构中初始化实例字段是错误的。在类中,必须初始化实例对象. 使用 new 运算符创建结构对象时,将创建该结构对象,并且调用适当的构造函数。与类不同的是,结构的实例化可以不使用 new 运算符。如果不使用 new,那么在初始化所有字段之前,字段将保持未赋值状态且对象不可用。对于结构,不像类那样存在继承。一个结构不能从另一个结构或类继承,而且不能作为一个类的基。但是,结构从基类 Object 继承。结构可实现接口,其方式同类完全一样。 [c ] 与 C 不同,无法使用 struct 关键字声明类。在 C# 中,类与结构在语义上是不同的。结构是值类型,而类是引用类型。 2, 装箱和拆箱(取消装箱) 装箱是值类型到 object 类型或到该值类型所实现的任何接口类型的隐式转换。将一个值的值装箱会分配一个对象实例并将该值复制到新的对象中。关键字 object. 取消装箱是从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换。取消装箱操作包括:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。 例: int i = 123; // A value type object box = i; // Boxing int j = (int)box; // Unboxing 装箱转换 取消装箱 3 , 隐式和显式 下列转换属于隐式转换:例:object o=i; 标识转换。 隐式数值转换。 隐式枚举转换。 隐式引用转换。 装箱转换。 隐式常数表达式转换。 用户定义的隐式转换。 下列转换属于显式转换: object 0=(object)i; 所有隐式转换。 显式数值转换。 显式枚举转换。 显式引用转换。 显式接口转换。 取消装箱转换。 用户定义的显式转换 4, delegate(委托) delegate void D(int x); class C{ public static void M1(int i) { /* ... */ } public static void M2(int i) { /* ... */ }} class{…….D cd1 = new D(C.M1);………….} 委托是一个数据结构,该数据结构引用一个静态方法,或引用一个对象实例和该对象的实例方法。在 C 或 C 中与委托最接近的是函数指针,但函数指针只能引用静态函数,而委托可以同时引用静态方法和实例方法。在后一种情况中,委托不仅存储对方法入口点的引用,还存储对调用其方法的对象的引用。与 C 函数指针不同,委托是完全面对对象的;与指向成员函数的 C 指针不同,委托同时封装对象实例和方法。委托声明定义从类 System.Delegate 派生的类。委托实例封装一个或多个方法,每个方法都被称为可调用实体。对于实例方法,可调用实体由一个实例和该实例上的方法组成。对于静态方法,可调用实体仅由一个方法组成。给定委托实例和适当的参数集,便可以用该参数集调用委托实例的所有方法。委托实例的一个有趣和有用的属性是它不了解或不关心它所封装的方法的类;真正重要的只是方法要与委托的类型兼容, 这使委托非常适合“匿名”调用。可选的形参表指定委托的参数,而返回类型则指示委托的返回类型。如果下面两个条件都为真,则方法和委托类型是兼容的:(兼容的概念就是可以用此声明的委托对方法进行委托). 1它们具有相同的参数数目,并且类型相同,顺序相同,参数修饰符也相同。 2它们的返回类型相同。 C# 中的委托类型是名称等效的,而不是结构等效的。(但是请注意:两个不同但结构上等效的委托类型的实例可能会比较为相等),准确地说,两个具有相同参数列表、签名和返回类型的不同的委托类型被认为是不同的委托类型。委托实例所封装的方法集合称为调用列表。 5, interface(接口) [attributes] [modifiers] interface identifier [:base-list] {interface-body}[;] 一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以从多个基接口继承,而类或结构可以实现多个接口。接口可以包含方法、属性、事件和索引器。接口本身不提供它所定义的成员的实现。接口只指定实现该接口的类或接口必须提供的成员。接口可以是命名空间或类的成员,并且可以包含下列成员的签名:方法属性 索引器. 一个接口可从一个或多个基接口继承。接口可由类实现。实现的接口的标识符出现在类的基列表中。被继承的接口称为该接口的显式基接口。当接口具有一个或多个显式基接口时,在该接口声明中,接口标识符后跟一个冒号以及由逗号分隔的基接口标识符列表。接口的基接口是显式基接口及其基接口。换言之,基接口集是显式基接口、它们的显式基接口(依此类推)的完全可传递的闭包。接口继承其基接口的所有成员。接口成员是通过 I.M 和 I[A] 形式的成员访问和索引访问表达式访问的,其中 I 是接口类型的实例,M 是该接口类型的方法、属性或事件,A 是索引器参数列表。接口可以由类和结构实现。为了指示类或结构实现接口,在该类或结构的基类列表中包含了接口标识符。在实现类或结构中定位接口成员的实现的过程称为接口映射。 6,object object 类类型是所有其他类型的最终基类。C# 中的每种类型都是直接或间接从 object 类类型派生的。可以把任何类型的数值给object类型. 7,string类型 string 类的实例表示 Unicode 字符串。尽管 string 是引用类型,但相等运算符(== 和 !=)被定义为比较 string 对象(而不是引用)的“值”(7.9.7 字符串相等运算符)。这使得对字符串相等性的测试更为直观。字符串为 string 类型并可写成两种形式,即用引号引起来和用 @ 引起来。用引号引起来的字符串括在双引号 (") 内, 并且可以包含包括换码序列在内的任何字符用 @ 引起来的字符串以 @ 开头,并用双引号引起来。用 @ 引起来的字符串以 @ 开头,并用双引号引起来。若要在一个用 @ 引起来的字符串中包括一个双引号,请使用两对双引号:@ 符号的另一种用法是使用碰巧成为 C# 关键字的被引用的 (/reference) 标识符。 8, 修饰符 修饰符作用 访问修饰符 public private internal protected 指定声明的类型和类型成员的可访问性。 访问不受限制 只有包含该类的成员的类可以访问 只有当前工程可以访问 只有包含该成员的类和继承的类可以访问 abstract指示某个类只能是其他类的基类。 const指定无法修改字段或局部变量的值。 event声明一个事件。 extern指示外部实现此方法。 override提供从基类继承的虚拟成员的新实现。 readonly声明一个字段,该字段只能赋值为该声明的一部分或者在同一类的构造函数中。 sealed指定类不能被继承。 static声明属于类型本身而不是属于特定对象的成员。 unsafe声明不安全的上下文。 virtual在派生类中声明其实现可由重写成员更改的方法或访问器。 volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中进行修改。 9,语句 语句是程序指令。除非特别说明,语句都按顺序执行。C# 具有下列类别的语句。 类别C# 关键字 选择语句if, else, switch, case 迭代语句do, for, foreach, in, while 跳转语句break, continue, default, goto, return 异常处理语句throw, try-catch, try-finally Checked 和 Uncheckedchecked, unchecked fixed 语句Fixed lock 语句Lock (1) foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用。此语句的形式如下: foreach (type identifier in expression) statement 若要循环访问集合,集合必须满足特定的要求。集合类型: 必须是 interface、class 或 struct。 必须包括返回类型的名为 GetEnumerator 的实例方法,例如 Enumerator(详见下文)。 Enumerator 类型(类或结构)必须包含: 一个名为 Current 的属性,它返回 ItemType 或者可以转换为此类型的类型。属性访问器返回集合的当前元素。 · 一个名为 MoveNext 的 bool 方法,它递增项计数器并在集合中存在更多项时返回 true。 有三种使用集合的方法: 使用上述指导创建一个集合。此集合只能用于 C# 程序。 1. 使用上述指导创建一个一般集合,另外实现 IEnumerable 接口。此集合可用于其他语言(如 Visual Basic)。 2. 在集合类中使用一个预定义的集合。 (2) throw 语句用于发出在程序执行期间出现反常情况(异常)的信号。throw 语句的形式为: throw [expression]; expression :异常对象。当在 catch 子句中再次引发当前异常对象时,它被省略。 (3)try –catch语句 try-catch 语句由一个 try 块和其后所跟的一个或多个 catch 子句(为不同的异常指定处理程序)构成。try-catch 语句采用下列形式之一: try try-block catch (exception-declaration-1) catch-block-1 catch (exception-declaration-2) catch-block-2 ... try try-block catch catch-block (4) fixed 防止变量被垃圾回收器重定位。 (5) lock lock 关键字将某个语句块标记为临界区。 6. 方法参数 如果为没有 ref 或 out 的方法声明一个参数,则此参数可以具有关联的值。可以在方法中更改该值,但当控制传递回调用过程时,不会保留更改的值。通过使用方法参数关键字,可以更改这种行为。如果没有ref,out则默认为值传递,虽然可以在方法中修改这个参数的值,但是修改后的值不会还会到调用该方法的程序中. params :params 关键字可以指定在参数数目可变处采用参数的方法参数 ref :引用传递 out : 7, namespace(名字空间) C#学习笔记(2)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:8092 出处: write by cash(天下第七) 2002.01.20 版权所有,翻录不究 cashcao@msn.com 选择 我身上携带着精神、信仰、灵魂 思想、欲望、怪癖、邪念、狐臭 它们寄生于我身体的家      我必须平等对待我的每一位客人 -----------伊沙:《原则》 我的名字是cash,所以我很功利主义; 我的星像是Leo,所以我很大男人主义; 我的语言是C#,所以我有点儿拿不定主义。 /* 你能看得出来,这不是一篇正规的技术文章,所以若你不小心从里边读到了一个爱情故事,可不要奇怪。有很多人用程序来表述爱情,在其中我能看到有Money,有Girl,有一些还涉及到Sex,但是我没有找到Love,我始终相信这世上有一种力量直接来自于爱情,到现在仍然相信。*/ C#(读作C sharp),是Microsoft公司新推出的(?)专为.NET设计的一门语言,号称“C/C++家族中第一种面向组件的语言”。很多人觉得它应该像C或者C++,但事实上它更像是java的一个clone,所以作为入门,读一下清华大学出版社出版的《Java 语言与面向对象程序设计》可能会对你有所帮助。本文假定你具备一切学习此语言所需的知识,没有也不要紧,我会在文中尽量列出相关的link,鉴于互联网瞬息万变的特点,若某一链接不可用,请自行至Google查询。 如前所述,我是一个狮子座男人,一度我认为学习Java会使我看起来与众不同,可是几个月以后我放弃了这个选择,我看了论坛里关于这两种语言孰优孰劣的讨论,最终选择了C#,请不要问我为何做出这样的选择,很多人认为中文是世界上最美丽的语言,可是华人世界以外有谁在讲汉语? 另外我发现论坛上学习Java的人都非常的有个性,当有人问起学习哪种语言更好时,他会打出几百个“JAVA”来,填满整个屏幕,也不说是为了什么。我觉得这样做未免有些太霸道了,如果你说这叫偏执狂我也不反对,虽然我是狮子座,可也不想被人这样看。 在C#刚刚推出的时候,大多数的程序员都不免吼上两句——不是因为高兴,而是因为又多了一种语言。他们觉得现在的语言太多了,没有必要再多出一种来添乱子。但是当他们看完C#的文档后又开始高兴起来,因为C#是如此简单:事实上,简单正是C#最大的特点。除此之外,它还具有现代、面向对象、类型安全、版本控制、兼容、灵活等特点。详细介绍请参阅rainbow(一个长着胡子的彩虹)翻译的<> ,前几章非常的有趣。 看完了前面几段,我的朋友提出了不同的意见:C#不是Java的Clone,它只是长得有些像Java而已,其实面向对象、中间语言什么的也不是什么新玩意儿,非Sun独创,有文为证:华山论剑:C#对Java。另外他对我上一集中说Microsoft越来越不要脸也极为生气,因为相比之下,Sun也不怎么样,微软已经将C#提交设在日内瓦的ECMA(European Computer Manufacturers' Association,国际标准化机构欧洲电子计算机工业会)并获得批准。Sun就从来没有将它的Java交给过ECMA,以至于正当Microsoft尽力在Visual J++基础上拓展Java功能,并使之与Windows操作系统紧密结合在一起的时候,Sun公司对Microsoft提出了法律诉讼,控告Microsoft违反了许可证协议中的条款,最终的结果是Microsoft公司不得不停止其Visual J++产品的开发。(Microsoft后来在完全面向.NET框架的开发语言集中加入了Visual J#.NET,算是对Java语言用户的一种照顾。) 有人说,选择C#意味着选择MS(在中国的程序员当中,这并不是件值得自豪的事。如果你还不能理解这种心情,可以试想一下有人很认真地对你讲他喜欢听毛宁的歌)。事实上,通过ECMA标准的C#可以由任何人在任何平台上设计出它的开发程序。比如Ximian公司的Mono工程,可以使开发者能够编写同时在Windows和Linux上运行的.Net程序,这些程序甚至还可能在其它非Windows的操作系统上运行,比方Unix。这一段时间我正在Linux下试验这个工程,遗憾的是,还没有成功。 一位师兄对此种比较颇为不屑,他认为只要选一种语言去学就好了,“重要的是你要用它,并且做的比别人好。”这让我想起来一直都很喜欢的那个歌:把你自己该做的那份工作,做得比别人出色。年轻的时候我老是用这句话自勉…… 写到这里我发现这个故事还没有提到桐桐,这篇东西是为她而作。我早在十八个月以前就答应了她,我答应了她很多事,但还没有完成一件,现在我要一件一件的去实现。所以这个故事还应该有个更好的开始。 2000年6月我大学毕业,从北京回到了石家庄,到一家什么都做的公司上班(做一个网站),最开始制作界面,然后用asp编程,如果你用过asp就会知道,这是个很无聊的工种。在此之前我在一家报社实习,为他们的网站做设计和动画。在那里我认识了桐桐。 那时候她还在上学。 >>>未完,待续... C#学习笔记(3)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:6938 出处: 开始 2000年6月我大学毕业,从北京回到了石家庄,正式开始了我的职业生涯。如前所述,一开始我使用的语言是asp,我一直认为这不能称之为编程,因为asp不是一种编程语言,把它叫做动态网页实现技术可能更好。另外,asp很简单,并且,简单就是它全部的特点--这使得它很容易就能学会(在后来的工作中,我接触到许多应聘的学生,他们都告诉我自己精通asp语言)。虽然学习起来很简单,但是在使用起来却不得不多费点儿劲儿:我还能记得自己晚上一个人在办公室用VI一步一步调试某一个网页的情景,每当遇到挫折失败的时候,总是想起给桐桐打一个电话,听听她的声音。如你所知,我总是遇到困难。 现在你能看出来,我不是高手,只是一个低手... 2000年6月我大学毕业,从北京回到了石家庄,同一时间(美国西部时间6月22日上午),微软公司在位于美国西雅图郊外的总部内邀请新闻记者、新闻分析家等约400人,举行了新闻发布会“Forum2000”,宣布正式推出.Net计划。这个计划中包括了新的网络计算平台(.Net Framework)、新的语言(C#)、新的开发工具(Visual Studio.Net)以及asp的下一个版本ASP.NET,后者最开始被称为ASP+。那时候我学习的主要兴趣就在ASP.NET上,并且通过这个窗口开始了解Microsoft.Net的各个方面。 ASP.NET仍然不能称之为一种编程语言,但是现在可以把它看作是一个创建、管理、部署Web应用程序的平台。可以使用任何.Net语言在这个平台上开发互联网应用程序,这其中当然包括C#。它们之间的关系可以从下图中看出: 这就是著名的.Net 平台结构图,从这个图上可以看到,ASP.NET、Windows Forms和VS.Net都不过是.Net开发平台的一部分,用于.Net应用程序的开发及展示。.Net 平台的核心技术为:通用语言运行时(CLR:Common Language Runtime)、基类库(Base Class Library)、.Net语言及Visual Studio.Net。 从这个图上也可以看出,.Net Framework是架构在Windows平台上的一个虚拟的运行平台,你可以想象将最下层的Windows换作其它的操作系统,比如说Linux,一样可以实现使用符合了CLS(Common Language Specification,通用语言规范)的.Net语言(VB.Net、C#、JScript.Net等)来创建ASP.NET或Windows Forms(可能会叫做Linux Forms)应用程序的功能,这其实就是我们前面介绍的Mono计划所要实现的功能。所以可以这么认为,理论上,C#是一种可以跨平台的语言,这很像Java,另一个比较像Java的地方是,C#也是一种(特殊意义上的)解释性的语言。同Java一样,C#编写的程序代码也是先通过C#编译器编译为一种特殊的字节代码(中间语言,Microsoft Intermediate Language,MSIL),运行的时候再经由特定的编译器(JIT编译器,Just In Time,JITer)编译为机器代码以供操作系统执行。 不仅是C#语言,所有.Net语言(将会包括我们常用的几十种现代的编程语言)都可以编写面向CLR的程序代码,这种代码在.Net中被称为托管代码(Managed Code),所有的Managed Code都直接运行在CLR上,具有与平台无关的特性。 解释性的语言很安全,并且可以通过它的运行平台为其赋予更多的功能,比如自动内存管理、异常处理等。事实上,C#语言的许多特点都是由CLR提供的,下面的CLR结构图说明了这一点。 可以看到,类型安全(Type Checker)、垃圾回收(Garbage Collector)、异常处理(Exception Manager)、向下兼容(COM Marshaler)、多线程支持(Thread Support)这些C#的特点都是由CLR来提供的。CLR最早被称为下一代Windows服务运行时(NGWS Runtime),是直接建立在操作系统层上的一个虚拟的运行环境,主要的功能是管理代码的运行。在.Net 平台结构图中,CLR的上面是.Net的基类库(Base Class Library,BCL),这组基类库包括了从基本输入输出到数据访问等各方面,提供了一个统一的面向对象的、层次化的、可扩展的编程接口。从.Net 平台结构图中也可以看到,基类库可以被各种语言调用和扩展,也就是说,不管是C#、VB.NET还是VC++.NET,都可以自由地调用.Net的基类库。事实上, C#并没有属于自己的类库,它所使用的编程接口就是.Net提供的基类库。所以,在决定使用C#时,真正需要费工夫学习的其实是.NET框架的基类库:C#自身只有区区77个关键词,而且其语法对许多程序员来说都是他们非常熟悉的。BCL则相反,它包含了超过4500个以上的类和无数的方法、属性,在你的C# 程序中随时都可能会用到它来完成自己的任务。 很多人都思考过应如何开始学习一种新的语言,对于一个有经验的编程人员来讲,这确非难事。但是对于一个对编写代码一无所知的人而言,如果你是以C#开始你的编程之旅的,数目繁多的概念及新名词可能会令你有些不知所措。这时候请注意你的学习顺序,任何一种编程语言的学习都是按照运行平台、语法、基类库直至各方面的应用这一顺序来进行的,但是在实际的学习中,它们之间并不是孤立的。推荐的方法是:对运行平台和语法有了一个整体的认识后,在应用中学习各种基类库的用法。鉴于C#这一语言的特殊性,全面了解它的运行平台(.Net Framework)必会使你的学习事半功倍。所以请记住上面提到的两个图,在以后的学习中,虽然可能不会明确的涉及到它们,但是在整个C#的学习过程中,它们却是无处不在的。 还有一个很重要的概念需要你明白,这就是公共语言架构(Common Language Infrastructure ,CLI)。CLI是CLR的一个子集,也就是.NET中最终对编译成MSIL代码的应用程序的运行环境进行管理的那一部分。在CLR结构图中CLI位于下半部分,主要包括类加载器(Class Loader)、实时编译器(IL To Native Compilers)和一个运行时环境的垃圾收集器(Garbage Collector)。CLI是.Net和CLR的灵魂,CLI为IL代码提供运行的环境,你可以将使用任何语言编写的代码通过其特定的编译器转换为MSIL代码之后运行其上,甚至还可以自己写MSIL代码在CLI上面运行。如你所知,欧洲计算机制造商协会(ECMA)已经于2001年10月13日批准C#语言规范(ECMA-334)成为一种新诞生的计算机产业标准。同时国际标准组织ISO也同意该标准进入该组织的审批阶段。并且,作为.Net与CLR的核心部分,CLI与C#也同时获得了ECMA的批准(ECMA-335)。拥有了C#与CLI这两项标准,你可以自己写出能够运行于任何操作系统上的.Net平台(只要你愿意)。如前所述,著名的Mono项目就是这么干的,Mono项目包括三个核心的部分:一个C#语言的编译器,一个CLI和一个类库。在Java的世界中,这项工作是由SUN公司完成的,SUN针对不同的操作系统开发出相应的Java虚拟机以便让一个由Java开发的应用程序运行在不同的操作系统上,但是迄今为止还没听说过微软有这方面打算(为用户提供非Windows系统的.Net平台)。 2000年的6月还有很多事情发生,2000年的6月我在学校做毕设,晚上就跑到系试验室看欧锦赛,我很喜欢的坎普君(Bergkamp)大放异彩,帮助荷兰队6比1大胜南斯拉夫,米哈伊洛维奇 (Mihajlovic)在比赛最后莫名的笑容永远留在了我的心中。说实话,那时候只顾着看EURO2000,可没管什么.Net、.Not。另外,离别的愁绪围绕在每个人的周围,广播里开始反反复复播放一些古老的歌曲,不知道为什么,恋曲1980却是那时候的最爱。 后来,我们都毕了业。如你所知,我离开了北京。 >>>未完,待续... C#学习笔记(4)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:8360 出处: 约定 //一个典型的用C#写就的HelloWorld程序 using System; class HelloWorld { public static void Main() { Console.WriteLine("Hello World !"); } } 我忘记自己第一次用C#向世界问好是在什么时候了,不过可以肯定我已经打过招呼了,那时候用的是beta1版。现在你可以到http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml去下载.Net Framework Software Development Kit (SDK)的正式版,其中包括了前面提到的.NET Framework, 以及书写、编译、测试、开发 .NET Framework 应用程序所需要的一切——文档、例子、命令行工具和编译器。安装之后就可以开发和运行C#程序了,不过一般的建议是:一定要看.Net Framework SDK中所带的文档与例子,如果能照着例子再写一遍那就再好不过了。 当我第一次看到C#代码的时候,同样认为它很像Java,一个形象的比喻是:C#和Java是一对双胞胎,从语法的角度来讲,它们共同的父亲当然非C++莫属(请注意,不是VC++)。对于一个学过Java语言的人来说(比如说在下),要理解这段代码实在是太容易了:第一行当然是注释了,C#支持两种注释方法,以"//"开始的单行注释和以"/*"、"*/"配对使用的多行注释。第二行(using System)导入了System这个包(在C#中被称之为名字空间,Namespace),可以让我们方便的调用Microsoft.Net基类库System中的所有类,在此例中使用了System名字空间中的"Console"类,用于在控制台窗口输出程序运行结果。如前所述,C#并没有内置的输入输出语句,所有需实现的功能都完全来自于.Net基类库。这一句的作用就是告诉编译器去哪里寻找Console类以便调用。 接下来声明了一个类HelloWorld,这个类中有一个特殊的方法Main(),每个可执行文件都需要有一个入口点,在C#中,这个入口点就是Main()方法,此方法将在程序启动时被调用。在这个方法中,Console是在命名空间System下的一个类,它表示的是控制台。这里调用其静态方法WriteLine()。如同C++一样,静态方法允许我们直接作用于类而非实例对象。WriteLine()函数接受字符串类型的参数"Hello World !",并把它送入控制台显示。如前所述,C#没有自己的类库,它直接获取Microsoft.NET系统类库。在这里正是通过获取Microsoft.NET系统类库中的System.Console.WriteLine()来完成我们想要的控制台输出操作。现在使用记事本来编写这段代码,并将它的文件名保存为HelloWorld.cs,其中".cs"是C#源代码文件的扩展名。然后在配置好C#编译器的命令行环境里键入"csc HelloWorld.cs"编译文件。可以看到编译输出文件HelloWorld.exe。键入HelloWorld执行这个文件可得到下面的输出: Hello World ! 这就是第一个C#的程序,我们使用csc.exe来编译它,对于这个C#编译器,有如下说明: 1. 它是随.Net Framework SDK免费发布的,可以在DOS命令行被调用 2. 它的使用方法如下:   csc SourceFile.cs /out:TargetFile.exe   如果不使用输出参数指定目标文件名,则默认输出为源文件名 3. 一般情况下,它在系统文件夹(Windows或WinNT)下的Microsoft.NET\Framework\v1.0.3705文件夹内 4. 如果你安装了VS.Net,从Visual Studio.NET Tools项目组中可以激活Visual Studio.NET Command Prompt窗口,这是一个配置好C#编译器的命令行环境 5. 使用csc.exe编译后的C#程序并不是机器代码(尽管拥有.exe的后缀名)。如前所述,C#程序只是被编译成了MSIL代码。 C#编译器(csc.exe)编译后的文件并不是一个严格意义上的可执行文件(并不包含机器代码),而是一个PE(portable executable)格式的文件,虽然它同样拥有.exe的后缀名。在这个PE文件中也不仅仅只包含中间语言,在其中还包含有元数据(Metadata)和一个由编译器添加的目标平台的标准可执行文件头。 中间语言,确切地说,应该称为微软中间语言(Microsoft Intermediate Language,MSIL),是由微软定义的一种界于源代码与机器码之间的一种语言。在CLR中,它首先会由特定的语言编译器将其包装成exe格式的伪代码(P代码)。再由特定的编译器将其转换为本地代码执行。对于微软中间语言,一个形象的比喻是:如果CLR是操作系统的话,那么微软中间语言就是.Net平台上的ASM汇编语言。它比大多数 CPU 机器语言更为高级,比如它可以理解对象类型,并具有创建和初始化对象、调用关于对象的虚拟方法以及直接操作处理数组元素的指令。它甚至还具有发现和捕获异常情况用于错误处理的指令。 元数据(Metadata)和MSIL共同存在于编译好的程序文件之中,描述了此程序包含的类型的定义、各种类型的签名及其它一些数据,相当于以前的类型库(Type Library),同时也记载了此程序所引用到的其它外部类。元数据的主要作用是将与代码有关的更多的信息提供给CLR。基本上,元数据用于如下各项任务:用于表示CLR用途的信息,如定位和装载类、内存中这些类的实例、解决调用、翻译IL为原始码、加强安全并设置运行时上下文边界。 一个由C#语言写就的源码文件在CLR环境中执行的过程是这样的:首先由C#编译器编译成包含了中间语言和元数据的PE文件,当我们在系统中调用这个文件时,CLR会启动一个编译器再将这个PE文件包含的MSIL代码转换成为托管的本地代码。转换MSIL代码为本地码的这个编译器就叫做JIT编译器(Just In Time,JITer)。请注意它并不是前面我们用到的C#编译器。 现在让我们看看JIT编译器是如何工作的:当PE文件被调用时,JIE编译器将其分解为MSIL和元数据,这时候MSIL并不直接让.Net去调用本地的系统接口,而是指定.Net系统去编译连接那些需要的CLR DLL,编译出百分之百的本地代码。整个的过程如下: 当一个类型被装载时,装载器创建一个存根(stub),并使它与类型的每一个方法相连接。当一个方法第一次被调用时,存根把控制交给JITer。JITer把MSIL编译为本地代码,并且把存根指针指向缓冲本地代码。已经被JITer编译的方法随后就直接调用已经产生的本地代码,减少了JITer编译和执行代码的时间。可以看到,JITer并不会一次性的将所有的MSIL都编译为本地代码,而是在我们需要时才即时编译,也就是说,有些代码可能从来都没有被编译过。很明显这样做的好处是既保证了运行期的安全性,又不会损失太多的效率。 这就是一个C#程序执行时的步骤。整个过程是这样的: 1) 由C#编译器将源代码编译为中间语言 2) 装入托管代码,这包括解决内存中的名字、表层类(laying out classes ),并且创建JIT编译所必需的存根。通过执行经常性校验,包括加强一些访问规则,类装载器同样也增强了安全性 3) 用JITer将 IL转换成原始代码 4) 装入元数据、校验类型安全和方法的完整性 5) 垃圾收集(GC)和异常处理 6) 描绘和查错服务 7) 管理线程和上下文以及远程管理。 不必全部理解这些概念,在以后的学习中将会一一的体会到它们的精彩,现在你需要做的(如果你还没这么干过的话),是找到ildasm.exe这个文件(一般情况下,它会和csc.exe在同一文件夹中)。顾名思义,这是一个MSIL的反汇编程序(.Net Framework IL Disassembler),在命令行窗口下输入ildasm helloworld.exe /out=helloworld.il就会得到两个文件:helloworld.il和helloworld.res。前者包括了反编译出来的元数据和MSIL代码,后者则是提取的资源文件。用记事本打开helloworld.il文件,可以看到它定义并实现了一个继承自System.Object 的HelloWorld类及两个函数:Main()和.ctor()。其中.ctor()是HelloWorld类的构造函数。在这个文件中还包括元数据和其它有关的信息。如果你觉得这样不够直观的话,可以在命令行窗口键入ildasm helloworld.exe,这样就可以启动ILDASM 窗口并向我们展示出反编译后的helloworld.exe文件。 请仔细将这些代码看上几遍,现在理解全部这些内容并不重要,但是希望你也能看一下文件中的元数据,这其中包含所有 Runtime 和编译器需要的有关程序集及其模块、类型和成员(如方法)的信息。 行文至此,我想谈一下学习。如你所知,在我们所处的环境中,学习总意味着是一个痛苦的过程,学习一种新知识好像总是为了自己的某种需求,我并不认为这样有什么不对,但我总觉着,除了拿到高薪和受人尊敬外,学习还应该带给我们更多的快乐。有些知识我们现在也许用不着,比如前面谈到的一些内容,但是我们了解了,就是一件值得高兴的事。 智慧本身就是好的,有一天我们都会死去,追求智慧的道路还会有人在走着。死掉以后的事我看不到。但在我活着的时候,想到这件事,心里就高兴。 ——王小波 今天是2002年4月7号,再过三天就是王小波的忌日了,不知道有多少人还会记得这个日子,还会记得这个人。本文的最后,我向大家推荐小波的作品——每一个心智成熟的人都应该读一读小波的文字。在他的杂文随笔集《沉默的大多数》中有一句话谈到了他作为程序员的一面: “今晚不把这段C++调通,老子就不睡了!” >>>未完,待续...
CruiseYoung提供的带有详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《Visual C++ 2010入门经典(第5版)》的源代码及课后练习答案 对应的书籍资料见: Visual C++ 2010入门经典(第5版) 基本信息 原书名: Ivor Horton's Beginning Visual C++ 2010 原出版社: Wrox 作者: (美)Ivor Horton 译者: 苏正泉 李文娟 出版社:清华大学出版社 ISBN:9787302239994 上架时间:2010-12-20 出版日期:2010 年12月 开本:16开 页码:1011 版次:5-1 编辑推荐   本书针对visual c++ 2010版本做了全面更新,介绍了最新开发环境,讲述了如何使用visual c++构建真实世界的应用程序。    采用了容易理解的讲授方法,并提供了详尽的示例,旨在帮助读者掌握编程技巧 内容简介   作者ivor horton采用了容易理解的讲授方法,并提供了详尽的示例,帮助读者迅速地成为一名优秀的c++编程人员。《visual c++ 2010入门经典(第5版)》针对visual c++ 2010版本进行了全面更新,介绍了最新的开发环境和如何使用visual c++构建现实世界中的应用程序。拥有本书,您就迈向了通往使用两种c++版本编写应用程序的成功之路,并成为一名优秀的c++编程人员。    主要内容    ·使用visual c++ 2010支持的两种c++语言技术讲述c++编程的基础知识    ·分享c++程序的错误查找技术,并介绍通用的调试原则讨论每一个windows应用程序的结构和基本元素    ·举例说明如何使用mfc开发本地windows应用程序    ·指导读者用c++c++/cli设计和创建大量的windows应用程序    ·为帮助读者掌握编程技巧,提供了大量可运行的示例和练习 作译者   Ivor Horton是撰著Java、C和C++编程语言图书的杰出作家之一。大家一致认为,他的著作独具风格,无论是编程新手,还是经验丰富的编程人员,都很容易理解其内容。在个人实践中,Ivor Horton也是一名系统顾问。他从事程序设计教学工作已经超过了25年。   苏正泉,1995年毕业于解放军信息工程学院计算机及应用专业,高级工程师。在IT项目管理、软件开发、系统管理和网络管理方面都有非常丰富的实践经验。曾发表过多篇计算机专业论文,并翻译过多部计算机专业技术书籍。   李文娟,中国石油大学(华东)硕士,现供职于国家行政学院,工作后一直从事软件开发和软件项目管理工作,对计算机语言、计算机体系结构、操作系统都非常熟悉,尤其是精通C和C++编程技术. 目录 封面 -19 封底 -18 扉页 -17 版权 -16 前言 -15 目录 -10 第1章 使用Visual C++ 2010编程 1 1.1 .NET Framework 1 1.2 CLR 2 1.3 编写C++应用程序 3 1.4 学习Windows编程 4 1.4.1 学习C++ 4 1.4.2 C++标准 5 1.4.3 属性 5 1.4.4 控制台应用程序 5 1.4.5 Windows编程概念 6 1.5 集成开发环境简介 7 1.5.1 编辑器 8 1.5.2 编译器 8 1.5.3 链接器 8 1.5.4 库 8 1.6 使用IDE 8 1.6.1 工具栏选项 9 1.6.2 可停靠的工具栏 10 1.6.3 文档 11 1.6.4 项目和解决方案 11 1.6.5 设置Visual C++ 2010的选项 23 1.6.6 创建和执行Windows应用程序 23 1.6.7 创建Windows Forms应用程序 26 1.7 小结 27 1.8 本章主要内容 28 第2章 数据、变量和计算 29 2.1 C++程序结构 29 2.1.1 main()函数 36 2.1.2 程序语句 36 2.1.3 空白 38 2.1.4 语句块 38 2.1.5 自动生成的控制台程序 39 2.2 定义变量 40 2.2.1 命名变量 40 2.2.2 声明变量 41 2.2.3 变量的初始值 42 2.3 基本数据类型 42 2.3.1 整型变量 43 2.3.2 字符数据类型 44 2.3.3 整型修饰符 45 2.3.4 布尔类型 46 2.3.5 浮点类型 46 2.3.6 字面值 47 2.3.7 定义数据类型的同义词 48 2.3.8 具有特定值集的变量 49 2.4 基本的输入/输出操作 50 2.4.1 从键盘输入 50 2.4.2 到命令行的输出 50 2.4.3 格式化输出 51 2.4.4 转义序列 52 2.5 C++中的计算 54 2.5.1 赋值语句 54 2.5.2 算术运算 55 2.5.3 计算余数 59 2.5.4 修改变量 60 2.5.5 增量和减量运算符 60 2.5.6 计算的顺序 63 2.6 类型转换和类型强制转换 64 2.6.1 赋值语句中的类型转换 65 2.6.2 显式类型转换 65 2.6.3 老式的类型强制转换 66 2.7 AUTO关键字 66 2.8 查看类型 67 2.9 按位运算符 67 2.9.1 按位AND运算符 68 2.9.2 按位OR运算符 69 2.9.3 按位EOR运算符 71 2.9.4 按位NOT运算符 71 2.9.5 移位运算符 71 2.10 lvalue和rvalue 73 2.11 了解存储时间和作用域 74 2.11.1 自动变量 74 2.11.2 决定变量声明的位置 76 2.11.3 全局变量 77 2.11.4 静态变量 80 2.12 名称空间 80 2.12.1 声明名称空间 81 2.12.2 多个名称空间 82 2.13 C++/CLI编程 84 2.13.1 C++/CLI特有的基本数据类型 84 2.13.2 命令行上的C++/CLI输出 87 2.13.3 C++/CLI特有的功能—— 格式化输出 88 2.13.4 C++/CLI的键盘输入 91 2.13.5 使用safe_cast 92 2.13.6 C++/CLI枚举 92 2.14 查看C++/CLI类型 96 2.15 小结 97 2.16 练习 97 2.17 本章主要内容 98 第3章 判断和循环 101 3.1 比较数据值 101 3.1.1 if语句 102 3.1.2 嵌套的if语句 104 3.1.3 嵌套的if-else语句 107 3.1.4 逻辑运算符和表达式 109 3.1.5 条件运算符 112 3.1.6 switch语句 113 3.1.7 无条件转移 116 3.2 重复执行语句块 117 3.2.1 循环的概念 117 3.2.2 for循环的变体 119 3.2.3 while循环 126 3.2.4 do-while循环 128 3.2.5 嵌套的循环 129 3.3 C++/CLI编程 132 3.4 小结 137 3.5 练习 138 3.6 本章主要内容 138 第4章 数组、字符串和指针 139 4.1 处理多个相同类型的数据值 139 4.1.1 数组 140 4.1.2 声明数组 140 4.1.3 初始化数组 143 4.1.4 字符数组和字符串处理 144 4.1.5 多维数组 147 4.2 间接数据访问 150 4.2.1 指针的概念 150 4.2.2 声明指针 150 4.2.3 使用指针 152 4.2.4 初始化指针 152 4.2.5 sizeof操作符 158 4.2.6 常量指针和指向常量的指针 159 4.2.7 指针和数组 161 4.3 动态内存分配 168 4.3.1 堆的别名—— 空闲存储器 168 4.3.2 new和delete操作符 168 4.3.3 为数组动态分配内存 169 4.3.4 多维数组的动态分配 171 4.4 使用引用 172 4.4.1 引用的概念 172 4.4.2 声明并初始化lvalue引用 172 4.4.3 声明并初始化rvalue引用 173 4.5 字符串的本地C++库函数 174 4.5.1 查找以空字符结尾的字符串的长度 174 4.5.2 连接以空字符结尾的字符串 174 4.5.3 复制以空字符结尾的字符串 176 4.5.4 比较以空字符结尾的字符串 177 4.5.5 搜索以空字符结尾的字符串 177 4.6 C++/CLI编程 179 4.6.1 跟踪句柄 180 4.6.2 CLR数组 181 4.6.3 字符串 195 4.6.4 跟踪引用 203 4.6.5 内部指针 204 4.7 小结 206 4.8 练习 206 4.9 本章主要内容 207 第5章 程序结构(1) 209 5.1 理解函数 209 5.1.1 需要函数的原因 210 5.1.2 函数的结构 210 5.1.3 使用函数 213 5.2 给函数传递实参 216 5.2.1 按值传递机制 216 5.2.2 给函数传递指针实参 217 5.2.3 给函数传递数组 219 5.2.4 给函数传递引用实参 222 5.2.5 使用const修饰符 224 5.2.6 rvalue引用形参 225 5.2.7 main()函数的实参 227 5.2.8 接受数量不定的函数实参 229 5.3 从函数返回值 231 5.3.1 返回指针 231 5.3.2 返回引用 233 5.3.3 函数中的静态变量 236 5.4 递归函数调用 238 5.5 C++/CLI编程 240 5.5.1 接受数量可变实参的函数 241 5.5.2 main( )的实参 242 5.6 小结 243 5.7 练习 243 5.8 本章主要内容 244 第6章 程序结构(2) 245 6.1 函数指针 245 6.1.1 声明函数指针 246 6.1.2 函数指针作为实参 249 6.1.3 函数指针的数组 250 6.2 初始化函数形参 250 6.3 异常 252 6.3.1 抛出异常 253 6.3.2 捕获异常 254 6.3.3 MFC中的异常处理 255 6.4 处理内存分配错误 256 6.5 函数重载 257 6.5.1 函数重载的概念 258 6.5.2 引用类型和重载选择 260 6.5.3 何时重载函数 260 6.6 函数模板 261 6.7 使用decltype操作符 263 6.8 使用函数的示例 265 6.8.1 实现计算器 265 6.8.2 从字符串中删除空格 268 6.8.3 计算表达式的值 268 6.8.4 获得项值 270 6.8.5 分析数 271 6.8.6 整合程序 274 6.8.7 扩展程序 275 6.8.8 提取子字符串 277 6.8.9 运行修改过的程序 279 6.9 C++/CLI编程 279 6.9.1 理解泛型函数 280 6.9.2 CLR版本的计算器程序 285 6.10 小结 290 6.11 练习 291 6.12 本章主要内容 292 第7章 自定义数据类型 293 7.1 C++中的结构 293 7.1.1 结构的概念 294 7.1.2 定义结构 294 7.1.3 初始化结构 294 7.1.4 访问结构的成员 295 7.1.5 伴随结构的智能感知帮助 298 7.1.6 RECT结构 299 7.1.7 使用指针处理结构 300 7.2 数据类型、对象、类和实例 301 7.2.1 类的起源 303 7.2.2 类的操作 303 7.2.3 术语 303 7.3 理解类 304 7.3.1 定义类 304 7.3.2 声明类的对象 305 7.3.3 访问类的数据成员 305 7.3.4 类的成员函数 307 7.3.5 成员函数定义的位置 309 7.3.6 内联函数 309 7.4 类构造函数 310 7.4.1 构造函数的概念 311 7.4.2 默认的构造函数 312 7.4.3 在类定义中指定默认的形参值 314 7.4.4 在构造函数中使用初始化列表 316 7.4.5 声明显式的构造函数 317 7.5 类的私有成员 318 7.5.1 访问私有类成员 320 7.5.2 类的友元函数 321 7.5.3 默认复制构造函数 323 7.6 this指针 325 7.7 类的const对象 327 7.7.1 类的const成员函数 327 7.7.2 类外部的成员函数定义 328 7.8 类对象的数组 329 7.9 类的静态成员 331 7.9.1 类的静态数据成员 331 7.9.2 类的静态函数成员 334 7.10 类对象的指针和引用 334 7.10.1 类对象的指针 334 7.10.2 类对象的引用 337 7.11 C++/CLI编程 338 7.11.1 定义值类类型 339 7.11.2 定义引用类类型 344 7.11.3 定义引用类类型的复制构造函数 346 7.11.4 类属性 346 7.11.5 initonly字段 358 7.11.6 静态构造函数 360 7.12 小结 360 7.13 练习 360 7.14 本章主要内容 361 第8章 深入理解类 363 8.1 类析构函数 363 8.1.1 析构函数的概念 363 8.1.2 默认的析构函数 364 8.1.3 析构函数与动态内存分配 366 8.2 实现复制构造函数 369 8.3 在变量之间共享内存 370 8.3.1 定义联合 371 8.3.2 匿名联合 372 8.3.3 类和结构中的联合 372 8.4 运算符重载 373 8.4.1 实现重载的运算符 373 8.4.2 实现对比较运算符的完全支持 376 8.4.3 重载赋值运算符 379 8.4.4 重载加法运算符 384 8.4.5 重载递增和递减运算符 387 8.4.6 重载函数调用操作符 388 8.5 对象复制问题 389 8.5.1 避免不必要的复制操作 389 8.5.2 应用rvalue引用形参 392 8.5.3 命名的对象是lvalue 394 8.6 类模板 399 8.6.1 定义类模板 400 8.6.2 根据类模板创建对象 402 8.6.3 使用有多个形参的类模板 405 8.6.4 函数对象模板 406 8.7 使用类 407 8.7.1 类接口的概念 407 8.7.2 定义问题 407 8.7.3 实现CBox类 408 8.8 组织程序代码 425 8.9 字符串的本地C++库类 427 8.9.1 创建字符串对象 427 8.9.2 连接字符串 429 8.9.3 访问与修改字符串 432 8.9.4 比较字符串 436 8.9.5 搜索字符串 439 8.10 C++/CLI编程 447 8.10.1 在值类中重载运算符 447 8.10.2 重载递增和递减运算符 452 8.10.3 在引用类中重载运算符 453 8.10.4 实现引用类型的赋值运算符 455 8.11 小结 456 8.12 练习 456 8.13 本章主要内容 457 第9章 类继承和虚函数 459 9.1 面向对象编程的基本思想 459 9.2 类的继承 460 9.2.1 基类的概念 461 9.2.2 基类的派生类 461 9.3 继承机制下的访问控制 464 9.3.1 派生类中构造函数的操作 467 9.3.2 声明类的保护成员 470 9.3.3 继承类成员的访问级别 473 9.4 派生类中的复制构造函数 474 9.5 友元类成员 477 9.5.1 友元类 479 9.5.2 对类友元关系的限制 479 9.6 虚函数 479 9.6.1 虚函数的概念 481 9.6.2 使用指向类对象的指针 483 9.6.3 使用引用处理虚函数 485 9.6.4 纯虚函数 486 9.6.5 抽象类 487 9.6.6 间接基类 489 9.6.7 虚析构函数 491 9.7 类类型之间的强制转换 494 9.8 嵌套类 495 9.9 C++/CLI编程 498 9.9.1 装箱与拆箱 499 9.9.2 C++/CLI类的继承 499 9.9.3 接口类 505 9.9.4 定义接口类 505 9.9.5 类和程序集 509 9.9.6 被指定为new的函数 513 9.9.7 委托和事件 514 9.9.8 引用类的析构函数和终结器 525 9.9.9 泛型类 527 9.10 小结 536 9.11 练习 536 9.12 本章主要内容 539 第10章 标准模板库 541 10.1 标准模板库的定义 541 10.1.1 容器 542 10.1.2 容器适配器 542 10.1.3 迭代器 543 10.1.4 算法 544 10.1.5 STL中的函数对象 545 10.1.6 函数适配器 545 10.2 STL容器范围 545 10.3 序列容器 545 10.3.1 创建矢量容器 546 10.3.2 矢量容器的容量和大小 549 10.3.3 访问矢量中的元素 553 10.3.4 在矢量中插入和删除元素 553 10.3.5 在矢量中存储类对象 555 10.3.6 排序矢量元素 559 10.3.7 排序矢量中的指针 560 10.3.8 双端队列容器 562 10.3.9 使用列表容器 565 10.3.10 使用其他序列容器 574 10.4 关联容器 588 10.4.1 使用映射容器 589 10.4.2 使用多重映射容器 600 10.5 关于迭代器的更多内容 600 10.5.1 使用输入流迭代器 601 10.5.2 使用插入迭代器 604 10.5.3 使用输出流迭代器 605 10.6 关于函数对象的更多内容 607 10.7 关于算法的更多内容 608 10.7.1 fill() 608 10.7.2 replace() 609 10.7.3 find() 609 10.7.4 transform() 610 10.8 lambda表达式 611 10.8.1 capture子句 612 10.8.2 捕获特定的变量 613 10.8.3 模板和lambda表达式 613 10.8.4 包装lambda表达式 617 10.9 C++/CLI程序的STL 618 10.9.1 STL/CLR容器 619 10.9.2 使用序列容器 619 10.9.3 使用关联容器 627 10.10 C++/CLI中的lambda表达式 633 10.11 小结 633 10.12 练习 633 10.13 本章主要内容 634 第11章 调试技术 635 11.1 理解调试 635 11.1.1 程序故障 636 11.1.2 常见故障 637 11.2 基本的调试操作 638 11.2.1 设置断点 639 11.2.2 设置跟踪点 641 11.2.3 启动调试模式 641 11.2.4 修改变量的值 645 11.3 添加调试代码 645 11.3.1 使用断言 645 11.3.2 添加自己的调试代码 647 11.4 调试程序 652 11.4.1 调用栈 652 11.4.2 单步执行到出错位置 653 11.5 测试扩展的类 656 11.6 调试动态内存 659 11.6.1 检查空闲存储器的函数 660 11.6.2 控制空闲存储器的调试操作 661 11.6.3 空闲存储器的调试输出 662 11.7 调试C++/CLI程序 668 11.7.1 使用调试类Debug和跟踪类Trace 668 11.7.2 在Windows Forms应用程序中获得跟踪输出 676 11.8 小结 677 11.9 本章主要内容 677 第12章 Windows编程的概念 679 12.1 Windows编程基础 679 12.1.1 窗口的元素 680 12.1.2 Windows程序与操作系统 681 12.1.3 事件驱动型程序 682 12.1.4 Windows消息 682 12.1.5 Windows API 682 12.1.6 Windows数据类型 683 12.1.7 Windows程序中的符号 684 12.2 Windows程序的结构 685 12.2.1 WinMain()函数 686 12.2.2 消息处理函数 696 12.2.3 简单的Windows程序 700 12.3 Windows程序的组织 701 12.4 MFC 702 12.4.1 MFC表示法 702 12.4.2 MFC程序的组织方式 702 12.5 使用Windows Forms 706 12.6 小结 707 12.7 本章主要内容 707 第13章 多核编程 709 13.1 并行处理基本知识 709 13.2 并行模式库 710 13.3 并行处理算法 710 13.3.1 使用parallel_for算法 710 13.3.2 使用parallel_for_each算法 712 13.3.3 使用parallel_invoke算法 714 13.4 真正的并行问题 715 13.5 临界区 728 13.5.1 使用critical_section对象 728 13.5.2 锁定代码节或解除代码节锁定 729 13.6 combinable类模板 731 13.7 任务和任务组 733 13.8 小结 736 13.9 练习 736 13.10 本章主要内容 736 第14章 使用MFC编写Windows程序 739 14.1 MFC的文档/视图概念 739 14.1.1 文档的概念 739 14.1.2 文档界面 740 14.1.3 视图的概念 740 14.1.4 链接文档和视图 741 14.1.5 应用程序和MFC 742 14.2 创建MFC应用程序 743 14.2.1 创建SDI应用程序 745 14.2.2 MFC Application Wizard的输出 748 14.2.3 创建MDI应用程序 757 14.3 小结 760 14.4 练习 760 14.5 本章主要内容 760 第15章 处理菜单和工具栏 763 15.1 与Windows进行通信 763 15.1.1 了解消息映射 764 15.1.2 消息类别 767 15.1.3 处理程序中的消息 767 15.2 扩展Sketcher程序 768 15.3 菜单的元素 769 15.4 为菜单消息添加处理程序 771 15.4.1 选择处理菜单消息的类 773 15.4.2 创建菜单消息函数 773 15.4.3 编写菜单消息函数的代码 775 15.4.4 添加更新用户界面的消息处理程序 778 15.5 添加工具栏按钮 781 15.5.1 编辑工具栏按钮的属性 782 15.5.2 练习使用工具栏按钮 783 15.5.3 添加工具提示 784 15.6 C++/CLI程序中的菜单和工具栏 785 15.6.1 理解Windows Forms 785 15.6.2 理解Windows Forms应用程序 786 15.6.3 在CLR Sketcher中添加菜单 788 15.6.4 添加菜单项的事件处理程序 790 15.6.5 实现事件处理程序 791 15.6.6 设置菜单项复选 792 15.6.7 添加工具栏 793 15.7 小结 797 15.8 练习 797 15.9 本章主要内容 797 第16章 在窗口中绘图 799 16.1 窗口绘图的基础知识 799 16.1.1 窗口工作区 800 16.1.2 Windows图形设备界面 800 16.2 Visual C++中的绘图机制 802 16.2.1 应用程序中的视图类 802 16.2.2 CDC类 803 16.3 实际绘制图形 811 16.4 对鼠标进行编程 813 16.4.1 鼠标发出的消息 813 16.4.2 鼠标消息处理程序 814 16.4.3 使用鼠标绘图 816 16.5 练习使用Sketcher程序 837 16.5.1 运行示例 838 16.5.2 捕获鼠标消息 838 16.6 在CLR中绘图 840 16.6.1 在窗体上绘图 840 16.6.2 添加鼠标事件处理程序 840 16.6.3 定义C++/CLI元素类 842 16.6.4 实现MouseMove事件处理程序 850 16.6.5 实现MouseUp事件处理程序 851 16.6.6 实现窗体的Paint事件处理程序 851 16.7 小结 852 16.8 练习 852 16.9 本章主要内容 853 第17章 创建文档和改进视图 855 17.1 创建草图文档 855 17.2 改进视图 859 17.2.1 更新多个视图 859 17.2.2 滚动视图 861 17.2.3 使用MM_LOENGLISH映射模式 865 17.3 删除和移动形状 866 17.4 实现上下文菜单 866 17.4.1 关联菜单和类 867 17.4.2 练习弹出菜单 870 17.4.3 突出显示元素 870 17.4.4 处理菜单消息 874 17.5 处理屏蔽的元素 881 17.6 扩展CLR Sketcher 882 17.6.1 坐标系统转换 882 17.6.2 定义草图类 885 17.6.3 在Paint事件处理程序中绘制草图 886 17.6.4 实现元素的突出显示 887 17.6.5 创建上下文菜单 891 17.7 小结 897 17.8 练习 897 17.9 本章主要内容 898 第18章 使用对话框和控件 899 18.1 理解对话框 899 18.2 理解控件 900 18.3 创建对话框资源 900 18.3.1 给对话框添加控件 901 18.3.2 测试对话框 902 18.4 对话框的编程 902 18.4.1 添加对话框类 902 18.4.2 模态和非模态对话框 903 18.4.3 显示对话框 903 18.5 支持对话框控件 906 18.5.1 初始化控件 906 18.5.2 处理单选按钮消息 907 18.6 完成对话框的操作 908 18.6.1 给文档添加线宽 908 18.6.2 给元素添加线宽 909 18.6.3 在视图中创建元素 910 18.6.4 练习使用对话框 910 18.7 使用微调按钮控件 911 18.7.1 添加Scale菜单项和工具栏按钮 911 18.7.2 创建微调按钮 911 18.7.3 生成比例对话框类 913 18.7.4 显示微调按钮 915 18.8 使用缩放比例 916 18.8.1 可缩放的映射模式 916 18.8.2 设置文档的大小 917 18.8.3 设置映射模式 918 18.8.4 同时实现滚动与缩放 919 18.9 使用CTaskDialog类 921 18.9.1 显示任务对话框 921 18.9.2 创建CTaskDialog对象 923 18.10 使用状态栏 925 18.11 使用列表框 929 18.11.1 删除比例对话框 929 18.11.2 创建列表框控件 929 18.12 使用编辑框控件 931 18.12.1 创建编辑框资源 931 18.12.2 创建对话框类 933 18.12.3 添加Text菜单项 934 18.12.4 定义文本元素 935 18.12.5 实现CText类 935 18.13 CLR Sketcher中的对话框和控件 940 18.13.1 添加对话框 940 18.13.2 创建文本元素 946 18.14 小结 953 18.15 练习 953 18.16 本章主要内容 953 第19章 存储和打印文档 955 19.1 了解序列化 955 19.2 序列化文档 956 19.2.1 文档类定义中的序列化 956 19.2.2 文档类实现中的序列化 957 19.2.3 基于CObject的类的功能 959 19.2.4 序列化的工作方式 960 19.2.5 如何实现类的序列化 961 19.3 应用序列化 961 19.3.1 记录文档修改 962 19.3.2 序列化文档 963 19.3.3 序列化元素类 965 19.4 练习序列化 968 19.5 打印文档 969 19.6 实现多页打印 972 19.6.1 获取文档的总尺寸 973 19.6.2 存储打印数据 973 19.6.3 准备打印 974 19.6.4 打印后的清除 976 19.6.5 准备设备上下文 976 19.6.6 打印文档 977 19.6.7 获得文档的打印输出 980 19.7 CLR Sketcher中的序列化和打印 981 19.7.1 了解二进制序列化 981 19.7.2 序列化草图 985 19.7.3 打印草图 995 19.8 小结 996 19.9 练习 996 19.10 本章主要内容 997 第20章 编写自己的DLL 999 20.1 了解DLL 999 20.1.1 DLL的工作方式 1000 20.1.2 DLL的内容 1003 20.1.3 DLL变体 1003 20.2 决定放入DLL的内容 1004 20.3 编写DLL 1005 20.4 小结 1011 20.5 练习 1011 20.6 本章主要内容 1011 前言   欢迎使用本书。通过学习本书,您可以使用Microsoft公司最新的应用程序开发系统,成为优秀的C++程序员。本书旨在讲述C++程序设计语言,然后讲述如何运用C++语言开发自己的Windows应用程序。在此过程中,读者将了解这一最新Visual C++版本所提供的很多激动人心的新功能,包括如何在自己的应用程序中充分利用多核处理器。   0.1 使用C++语言编程   Visual C++ 2010支持两种截然不同但又紧密相关的C++语言,即ISO/IEC标准C++(本书称其为本地C++)和C++/CLI。虽然很多专业开发人员选用本地C++,尤其是当性能是需要考虑的主要因素时,但是C++/CLI和Windows Forms应用程序带来的开发速度和简易性使得C++/CLI也成了基本的语言。因此,本书将深入讨论这两种版本的C++语言。   Visual C++ 2010完全支持原来的ISO/IEC标准C++语言,同时还支持即将发布的ISO/IEC标准C++提供的一些功能强大的新特性。因此,本书不仅涵盖ISO/IEC标准C++的原有功能,同时还会介绍新语言特性。   Visual C++ 2010也支持C++/CLI,它是Microsoft公司作为本地C++的扩展而开发的C++版本。C++/CLI背后的思想是向本地C++添加一些特性,从而能够开发以.NET支持的虚拟机环境为目标的应用程序。这就将C++添加到能使用.NET Framework的其他语言(例如,BASIC和C#)中。C++/CLI语言目前是一个ECMA标准,同时也符合定义.NET虚拟机环境的CLI标准。   Visual C++ 2010的这两种C++版本互为补充,各自完成不同的任务。ISO/IEC C++用于开发在本地计算机上运行的高性能应用程序,而C++/CLI专门为.NET Framework开发应用程序。掌握了使用这两种C++版本开发应用程序的基础知识之后,就能够充分利用Visual C++ 2010。   0.2 开发Windows应用程序   充分理解C++之后,就可以着手开发Windows应用程序。Microsoft基本类(Microsoft Foundation Classes,MFC)封装了Windows API,提供了全面而易于使用的功能,从而能够使用本地C++开发高性能的Windows应用程序。   当编写本地C++程序时,可以从自动生成的代码中获得大量帮助,但仍然需要亲自编写大量C++代码。我们不仅需要对面向对象编程(OOP)技术有扎实的理解,而且需要充分了解Windows编程所涉及的各个方面。本书会介绍所有这些知识点。   C++/CLI虽然针对.NET Framework开发,但同时也是Windows Forms应用程序开发的载体。开发Windows Forms应用程序时,在不用编写一行代码的情况下,即使不能创建应用程序交互所需的用户界面的所有元素,也可以创建其中的很多元素。当然,仍然需要定制Windows Forms应用程序,才能完成相应的任务,但开发时间与使用本地C++创建应用程序相比只占一小部分。当给Windows Forms应用程序添加定制代码时,即使这部分代码只占到代码总量的很小比例,也仍然要求我们深入理解C++/CLI语言,才能做到游刃有余。本书旨在介绍这些知识。   0.3 高级库功能   并行模式库(Parallel Patterns Library,PPL)是Visual C++ 2010增加的一个令人激动的新功能,通过此功能,我们可以轻松编写使用多处理器的程序。在过去,为多处理器编程并非易事,但有了PPL,这就确实变得很容易了。本书将介绍PPL的各种使用方式,从而加快计算密集型应用程序的执行速度。   0.4 本书读者对象   本书针对任何想要学习如何使用Visual C++ 2010编写在Microsoft Windows操作系统下运行的C++应用程序的读者。阅读本书不需要预先具备任何特定编程语言的知识。如果属于下列4种情形之一,您就适合学习本教程:   ·属于编程新手,十分渴望投入编程世界,并最终掌握C++。要取得成功,您至少需要对计算机的工作原理有大体的理解——包括内存的组织方式以及数据和指令的存储方式。   ·具备一些其他语言的编程经验,如BASIC;渴望学习C++,并想提升实际的Microsoft Windows编程技能。   ·有一些使用C语言或C++语言的经验,但使用环境不是Microsoft Windows;希望使用最新的工具和技术,扩展在Windows环境下编程的技能。   ·有一些C++知识,并希望扩展C++技能,成为会使用C++/CLI的编程人员。   0.5 本书主要内容   本书实质上涵盖了两大主题:C++编程语言以及如何使用MFC或.NET Framework编写Windows应用程序。在开发完全成熟的Windows应用程序之前,需要具备相当水平的C++知识,因此,首先学习这本C++教程。 .  本书的第一部分通过可运行于两种C++语言版本上的一个详细的循序渐进式教程,讲授了使用Visual C++ 2010支持的两种C++语言技术编写C++程序的基础知识。您将了解本地ISO/IEC C++语言的语法和用法,并通过一系列范围广泛的可工作示例,获得实际运用它的经验和信心。本书也提供了一些练习,可以检验所学的知识,并且可以下载练习题答案。而C++/CLI作为本地C++的扩展来学习,这仍然是通过一些可运行的示例来说明每一个特性的工作原理。   当然,本语言教程也介绍和说明了C++标准库功能的用法,因为开发程序时极有可能使用它们。随着深入地学习C++语言,您的标准库知识会不断增加。还将学习标准模板库(Standard Template Library,STL)以两种形式——即本地C++版本和C++/CLI版本——提供的强大工具。另外,本书还用一章的篇幅专门讲述新增的并行模式库(PPL)功能,从而能够利用PC的多核处理功能来开发计算密集型应用程序。   对C++的运用有信心之后,就可以继续学习Windows编程了。通过创建超过2000行代码的大型可运行的应用程序,学习如何使用MFC来开发本地Windows应用程序。开发此应用程序贯穿多章内容,使用到了MFC提供的一系列用户界面功能。为学习如何使用C++/CLI编写Windows程序,相应地开发了一个与本地C++应用程序具有相似用户界面特性的Windows Forms应用程序。   0.6 本书结构   本书内容的结构安排如下:   ·第1章介绍使用C++编写本地应用程序和.NET Framework应用程序所需要理解的基本概念,以及在Visual C++ 2010开发环境中体现的主要思想,还叙述了如何使用Visual C++ 2010的功能来创建本书其余部分要学习的各种C++应用程序。   ·第2~9章讲授两种C++语言版本。第2~9章内容的组织方式都相似:各章的前半部分讨论本地C++语言的元素,后半部分讨论如何在C++/CLI中提供相同的功能。   ·第10章介绍如何使用标准模板库(Standard Template Library,STL)。STL是一组功能强大且全面的工具,用来组织和操作本地C++程序中的数据。由于STL是独立于应用程序的,因此可以在上下文中大量应用它。第10章还介绍了Visual C++ 2010新增的STL/CLR。它是C++/CLI应用程序的STL版本。   ·第11章介绍了在C++程序中查找错误的技术。涵盖了调试程序的一般原则,以及Visual C++ 2010提供的基本特性,这些特性可以帮助我们查找代码中的错误。   ·第12章讨论Microsoft Windows应用程序的组织方式,并描述和展示了在所有Windows应用程序中都存在的基本元素。本章解释了以本地C++语言编写的、使用Windows API和MFC的Windows应用程序示例,还给出了一个使用C++/CLI语言编写的Windows Forms应用程序的基础示例。   ·第13章介绍了如何在PC有多核处理器的情况下编写程序以使用多个处理器。通过一些完整的工作示例展示了并行处理的基本技术,这些示例Windows API应用程序是计算密集型程序。   ·第14~19章讲述Windows编程。详细描述了如何使用MFC提供的构建GUI的功能编写本地C++ Windows应用程序以及如何在C++/CLI Windows应用程序中使用.NET Framework。我们将学习如何创建并使用通用控件来构建应用程序的图形用户界面,还将学习如何处理因用户与程序的交互作用而产生的事件。除了学习构建GUI的技术以外,还将从开发该应用程序的过程中学到如何打印文档,以及如何在磁盘上保存应用程序数据。   ·第20章讲述为使用MFC创建自己的库而需要知道的基本知识。我们将了解可以创建的不同种类的库,还将开发能够与前6章开发的应用程序协同工作的示例。   本书各章内容都包括许多工作示例,通过这些示例阐明所讨论的编程技术。每章结束时都总结了该章所讲述的要点,大多数章节都在最后给出了一组练习,您可以应用所学的技术来试着解答这些练习。练习的答案连同书中的所有代码都可以从http://www.wrox.com和http://www.tupwk.com.cn/ downpage下载。关于C++语言教程使用的示例都是使用简单的命令行输入和输出的控制台程序。这种方法使我们能够在不陷入复杂的Windows GUI编程的情况下,学习C++的各种功能。实际上,只有在透彻地理解编程语言之后,才能进行Windows 编程。   如果希望使学习过程尽可能简单,或者如果您是程序设计初学者,那么最初可以只学习本地C++编程语言。讲授C++语言的各章(第2~9章)都是首先讨论本地C++功能的特定方面,然后再讨论C++/CLI在相同的上下文中引入的新功能。以这种方式组织各章内容的原因在于,C++/CLI是作为ISO/IEC标准语言的扩展定义的,对C++/CLI的理解是以对ISO/IEC C++的理解为基础的。因此,您可以只阅读各章中的本地C++部分,而忽略后面的C++/CLI部分。然后可以继续使用本地C++开发Windows应用程序,而免去记住两种语言版本的苦恼。在熟悉了ISO/IEC C++之后,您可以回头重新学习C++/CLI。当然,如果您已经有一些编程经验,也可以逐章进行学习,从而同步增加这两种C++语言版本的知识。   0.7 使用本书的前提   为了充分地使用本书,需要可支持MFC的某个Visual C++ 2010(或Visual Studio 2010)版本。需要注意的是,免费的Visual C++ 2010 Express Edition版本是不行的。因为此版本只提供C++编译器以及对基本Windows API的访问,并没有提供MFC库。因此,Visual C++ 2010(或Visual Studio 2010)的任何付费版本都能够编译并执行本书的所有示例。   0.8 源代码   读者在阅读本书提供的代码时,既可以亲自输入所有代码,也可以使用随书提供的代码文件。本书所有代码均可以从http://www.wrox.com/或www.tupwk.com.cn/downpage网站下载。进入该网站后,读者可以根据本书的书名查找本书(既可以使用搜索框,也可以使用书名列表进行查找),然后单击本书详细内容页面上提供的Download Code链接,就可以下载本书提供的所有代码。   注意:   由于许多书籍名称与本书类似,读者也可以通过ISBN进行查找,本书的ISBN为:978-0-470-50088-0。   另外,读者可以从前面提到的CodePlex网站下载本书或其他Wrox书籍的代码,也可以从Wrox的代码下载页面http://www.wrox.com/dynamic/books/download.aspx和http://www. tupwk.com.cn/downpage下载本书或其他Wrox书籍的代码。   源代码下载成功后,读者用任一解压工具将其解压即可。   0.9 勘误表   为了避免本书文字和代码中存在错误,我们已经竭尽全力。然而,世界上并不存在完美无缺的事物,所以本书可能仍然存在错误。如果读者在我们编写的某本书籍中发现了诸如拼写错误或代码缺陷等问题,那么请告诉我们,我们对此表示感谢。利用勘误表反馈错误信息,可以为其他读者节省大量时间,同时,我们也能够受益于读者的帮助,这样有助于我们编写出质量更高的专业著作。   如果读者需要参考本书的勘误表,请在网站http://www.wrox.com中用搜索框或书名列表查找本书书名。然后,在本书的详细内容页面上,单击Book Errata链接。在随后显示的页面中,读者可以看到与本书相关的所有勘误信息,这些信息是由读者提交、并由Wrox的编辑们加上的。通过访问http://www.wrox.com/misc-pages/booklist.shtml,读者还可以看到Wrox出版的所有书籍的勘误表。   如果读者没有在Book Errata页面上找到自己发现的错误,那么请转到页面http://www. wrox.com/contact/techsupport.shtml,针对您所发现的每一项错误填写表格,并将表格发给我们,我们将对表格内容进行认真审查,如果确实是我们书中的错误,我们将在该书的Book Errata页面上标明该错误信息,并在该书的后续版本中改正。   0.10 关于p2p.wrox.com网站   如果读者希望能够与作者进行讨论,或希望能够参与到读者的共同讨论中,那么请加入p2p.wrox.com论坛。该论坛是一个基于Web的系统,读者可以在论坛发表与Wrox出版的书籍及相关技术的信息,并与其他读者和技术用户进行讨论。论坛提供了订阅功能,可以将与读者所选定主题相关的新帖子定期发送到读者的电子邮箱。Wrox的作者、编辑、业界专家,以及其他读者都会参与论坛中的讨论。   读者可以在http://p2p.wrox.com参与多个论坛的讨论,这些论坛不仅能够帮助读者更好地理解本书,还有助于读者更好地开发应用程序。如果读者希望加入论坛,那么请按照以下步骤执行:   (1) 进入http://p2p.wrox.com页面,单击Register链接。   (2) 阅读使用条款,然后单击Agree按钮。   (3) 填写必要的信息及可选信息,然后单击Submit按钮。   (4) 随后读者会收到一封电子邮件,邮件中说明了如何验证账户并完成整个加入过程。   读者无须加入P2P论坛即可阅读论坛消息,但如果需要发表主题或发表回复,那么必须加入论坛。   成功加入论坛后,读者就可以发表新主题了。此时,读者还可以回复其他用户发表的主题。读者在任何时间都可以阅读论坛信息,如果需要论坛将新的信息发送到自己的电子邮箱,那么可以单击论坛列表中论坛名称旁的Subscribe to this Forum图标完成这项功能设置。   如果读者需要获得更多与Wrox P2P相关的信息,请阅读P2P FAQs,这样可以获得大量与P2P和Wrox出版的书籍相关的具体信息。阅读FAQs时,请单击P2P页面上的FAQs链接。   

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧