仓酷云
标题:
ASP.NET教程之C++/CLI中类的实质剖析仓酷云
[打印本页]
作者:
活着的死人
时间:
2015-1-18 11:30
标题:
ASP.NET教程之C++/CLI中类的实质剖析仓酷云
我觉得这个学习方法很重要。初学者应该跟我一样有同样一个毛病。那就是急于求成。很想就自己做出个小小的系统来。可真要动手,却又茫然而不知所措。为什么会这样呢?因为我们没有耐心去学习基础知识。写根本看不到什么效果的测试代码。VisualC++2005(VisualC++8.0)中的C++撑持C++/CLI,C++/CLI同时撑持C++言语特征和.NET编程言语特征,能够完成.NETCLI不撑持而C++撑持的言语特征,比方多重承继等,还撑持夹杂Assembly,能够在统一Assembly中夹杂利用CIL代码和本机代码。
C++/CLI的功效要比C#强的多,更合适作为剖析.NETFramework内核的编程言语,笔者试编写了一个C++/CLI程序,试图经由过程反汇编编译天生的.NETAssembly可实行文件,剖析C++/CLI中类的实质。
笔者编写的这个程序是一个实验性的单数和实数盘算程序,上面是C++主程序(TypesSample1_CPP.cpp):
//TypesSample1_CPP.cpp:主项目文件。
#include"stdafx.h"
usingnamespaceSystem;
//Complex类,.NETCTS值范例。
valueclassComplex
{
public:
doubleRe;
doubleIm;
Complex(doubleRe,doubleIm);
};
Complex::Complex(doubleRe,doubleIm)
{
this->Re=Re;
this->Im=Im;
}
//ComplexMath范例,.NETCTS援用范例。
refclassComplexMath
{
public:
ComplexAdd(ComplexOpNum1,ComplexOpNum2);
ComplexMinus(ComplexOpNum1,ComplexOpNum2);
};
ComplexComplexMath::Add(ComplexOpNum1,ComplexOpNum2)
{
ComplexResult1;
Result1.Re=OpNum1.Re+OpNum2.Re;
Result1.Im=OpNum1.Im+OpNum2.Im;
returnResult1;
}
ComplexComplexMath::Minus(ComplexOpNum1,ComplexOpNum2)
{
ComplexResult1;
Result1.Re=OpNum1.Re-OpNum2.Re;
Result1.Im=OpNum1.Im-OpNum2.Im;
returnResult1;
}
//DisplayComplex类,C++类。
classDisplayComplex
{
public:
voidDisplay(ComplexC);
};
voidDisplayComplex::Display(ComplexC)
{
String^ReStr,^ImStr;
ReStr=C.Re.ToString();
ImStr=C.Im.ToString();
Console::WriteLine(ReStr+"+"+ImStr+"i");
}
//RealMath类,C++类,编译本钱机代码。
#pragmaunmanaged
classRealMath
{
public:
doubleAdd(doubleOpNum1,doubleOpNum2);
doubleMinus(doubleOpNum1,doubleOpNum2);
};
doubleRealMath::Add(doubleOpNum1,doubleOpNum2)
{
returnOpNum1+OpNum2;
}
doubleRealMath::Minus(doubleOpNum1,doubleOpNum2)
{
returnOpNum1-OpNum2;
}
#pragmamanaged
//主函数
intmain(array<System::String^>^args)
{
//C++/CLI中,.NETCTS值范例变量间接界说。
ComplexC1(2,2),C2(1,1);
ComplexC3,C4;
//C++/CLI中,.NETCTS援用范例的对象一般利用gcnew关头字创立。
ComplexMath^CM1=gcnewComplexMath();
//C++/CLI中,C++类的对象仍旧利用new关头字创立。
DisplayComplex*DC1=newDisplayComplex();
RealMath*RM1=newRealMath();
C3=CM1->Add(C1,C2);
C4=CM1->Minus(C1,C2);
DC1->Display(C3);
DC1->Display(C4);
Console::WriteLine(RM1->Add(2,1));
Console::WriteLine(RM1->Minus(2,1));
//C++/CLI中,利用new关头字创立的C++类的对象,仍旧必要利用delete关头字删除。
deleteDC1;
deleteRM1;
return0;
}
程序中Complex类利用valueclass关头字界说,属于.NETCTS值范例(ValueTypes);ComplexMath类利用refclass关头字界说,属于.NETCTS援用范例(ReferenceTypes);DisplayComplex和RealMath类则利用class关头字界说,属于C++类,个中RealMath类的界说和完成还利用了#pragmaunmanaged和#pragmamanaged编译唆使,申明RealMath类编译本钱机代码,而不编译成CIL代码,以完成夹杂Assembly。
程序编译运转后,失掉了预期了局:
3+3i
1+1i
3
1
将编译后天生的可实行文件(Assembly)TypesSample1_CPP.exe利用IDAPro4.8反汇编(不要利用ildasm.exe反汇编),注重利用.NETExecutable文件格局反汇编,反省天生的IL汇编言语程序,能够看到以下IL汇编言语代码(往失落了部分正文,另有一部分正文是笔者加的,下同):
……
//Complex类,从System.ValueType类派生,明显是值范例。
.classprivatesequentialsealedansiComplexextends[mscorlib]System.ValueType
{
.fieldpublicfloat64Re
.fieldpublicfloat64Im
.methodpublichidebysigspecialnamevoid.ctor(float64Re,float64Im)
{
ldarg.0
ldarg.1
stfldfloat64Complex::Re
ldarg.0
ldarg.2
stfldfloat64Complex::Im
ret
}
}
//ComplexMath类,从System.Object类派生,明显是援用范例。
.classprivateautoansiComplexMathextends[mscorlib]System.Object
{
.methodpublichidebysigvalueclassComplexAdd(valueclassComplexOpNum1,valueclassComplexOpNum2)
{
.locals(valueclassComplexV0)
ldloca.s0
initobjComplex
ldloca.s0
ldarga.s1
ldfldfloat64Complex::Re
ldarga.s2
ldfldfloat64Complex::Re
add
stfldfloat64Complex::Re
ldloca.s0
ldarga.s1
ldfldfloat64Complex::Im
ldarga.s2
ldfldfloat64Complex::Im
add
stfldfloat64Complex::Im
ldloc.0
ret
}
.methodpublichidebysigvalueclassComplexMinus(valueclassComplexOpNum1,valueclassComplexOpNum2)
{
.locals(valueclassComplexV0)
ldloca.s0
initobjComplex
ldloca.s0
ldarga.s1
ldfldfloat64Complex::Re
ldarga.s2
ldfldfloat64Complex::Re
sub
stfldfloat64Complex::Re
ldloca.s0
ldarga.s1
ldfldfloat64Complex::Im
ldarga.s2
ldfldfloat64Complex::Im
sub
stfldfloat64Complex::Im
ldloc.0
ret
}
.methodpublichidebysigspecialnamevoid.ctor()
{
ldarg.0
callvoid[mscorlib]System.Object::.ctor()
ret
}
}
//DisplayComplex类,C++类,编译后酿成了值范例,并且办法成员消散了。
.classprivatesequentialsealedansiDisplayComplexextends[mscorlib]System.ValueType
{
}
//RealMath类,C++类,编译后酿成了值范例,并且办法成员消散了。
.classprivatesequentialsealedansiRealMathextends[mscorlib]System.ValueType
{
}
……
DisplayComplex类和RealMath类这两个C++类,办法成员为何消散了?进一步反省的IL汇编言语程序,还能够看到以下IL汇编言语代码:
……
.moduleTypesSample1_CPP.exe
……
//DisplayComplex类的Display办法,注重这是一个全局办法(函数),可是仍旧利用CIL代码完成。
.methodassemblystaticvoidDisplayComplex.Display(modopt([mscorlib]System.Runtime.CompilerServices.IsConst)modopt([mscorlib]System.Runtime.CompilerServices.IsConst)valueclassDisplayComplex*C,valueclassComplex)
{
.locals(classSystem.StringV0,
float64V1,
float64V2)
ldarga.s1
ldfldfloat64Complex::Re
stloc.2
ldloca.s2
callclassSystem.String[mscorlib]System.Double::ToString()
ldarga.s1
ldfldfloat64Complex::Im
stloc.1
ldloca.s1
callclassSystem.String[mscorlib]System.Double::ToString()
stloc.0
ldstr"+"
callclassSystem.String[mscorlib]System.String::Concat(classSystem.String,classSystem.String)
ldloc.0
callclassSystem.String[mscorlib]System.String::Concat(classSystem.String,classSystem.String)
ldstr"i"
callclassSystem.String[mscorlib]System.String::Concat(classSystem.String,classSystem.String)
callvoid[mscorlib]System.Console::WriteLine(classSystem.String)
ret
}
//main函数(主函数),注重这是一个全局办法。
.methodassemblystaticint32main(classSystem.String[]args)
{
……
}
……
//RealMath类的Add办法,注重这是一个全局办法,利用PInvoke(平台挪用)挪用本机代码完成。
.methodpublicstaticpinvokeimpl(/*Nomap*/)modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall)float64RealMath.Add(modopt([mscorlib]System.Runtime.CompilerServices.IsConst)modopt([mscorlib]System.Runtime.CompilerServices.IsConst)valueclassRealMath*,float64,float64)nativeunmanaged
{
}
//RealMath类的Minus办法,注重这是一个全局办法,利用PInvoke(平台挪用)挪用本机代码完成。
.methodpublicstaticpinvokeimpl(/*Nomap*/)modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall)float64RealMath.Minus(modopt([mscorlib]System.Runtime.CompilerServices.IsConst)modopt([mscorlib]System.Runtime.CompilerServices.IsConst)valueclassRealMath*,float64,float64)nativeunmanaged
{
}
……
读者读到这里大概会感应有些奇异:不是说.NET编程言语(比方C#)源程序完整由类组成吗?那末编译后天生的可实行文件反汇编后,就不该该另有全局办法(函数),为何反汇编了局中居然呈现了全局办法呢?
实践上,.NETCLI的第2部分“元数据的界说和语义”中已明白申明:字段和办法都能够是全局的,也就是不在任何一个范例中界说,而在模块(Module)中间接界说的字段和办法。
固然C#等.NET编程言语纷歧定撑持全局字段和全局办法,可是C++/CLI是撑持全局字段和全局办法的,C++/CLI中的C++全局变量和全局函数,就是利用全局字段和全局办法完成的。
实在,说.NET编程言语源程序中完整没有全局字段和全局办法,这类说法自己就是不太公道的,范例中的静态成员,包含静态字段和静态办法,实质上不也就相称于加了范例名“名字空间”——相称于“前缀”的全局字段和全局办法吗?
C++言语特征分明分歧于C#,C++/CLI仍旧撑持C++言语特征。比方:在C#中,利用struct关头字界说的布局属于.NETCTS值范例,利用class关头字界说的类属于.NETCTS援用范例,可是在C++/CLI中,struct关头字和class关头字是等价的,区分只是利用struct关头字界说的类中,成员默许是public的,而利用class关头字界说的类中,成员默许是private的。
回到上述反汇编了局,从反汇编了局中,能够分明看出以下几点:
1、C++/CLI中间接利用class大概struct关头字界说类,并非间接界说.NETCTS中的范例。C++/CLI中界说.NETCTS中的范例,自界说值范例必需利用valueclass大概valuestruct关头字界说,自界说援用范例必需利用refclass大概refstruct关头字界说。
2、关于C++/CLI中的C++类,也就是间接利用class大概struct关头字界说的类,实在现办法,包含类的对象的完成办法,仍旧与传统C++完成类和对象的办法类似:对象的属性(字段大概成员变量)和办法(成员函数)分别,对象计划成包括对象属性的数据布局,办法计划成针对对象属性的历程(函数),将包括对象属性的数据布局的援用(指针)作为办法历程的参数,让办法历程针对特定对象的属性举行操纵,如许包括对象属性的数据布局和办法历程在逻辑上就组成一般意义上的对象。以是C++类编译后,实践上对应的.NETCTS范例中只包括字段成员,办法成员酿成了全局办法。由于传统C++中,类都相称于值范例,C++对象变量间接存储C++对象自己,以是C++/CLI中的C++类编译后对应的.NETCTS范例也都是值范例。
3、关于夹杂Assembly中编译本钱机代码的类,实践上只要办法的完成编译成了本机代码,经由过程平台挪用(PInvoke)举行挪用,好像C++/CLI大概C#挪用本机代码DLL一样。
能够看出,C++/CLI中,除非一个类被明白界说成.NETCTS中的范例,C++类和对象的完成在实质上仍旧和传统C++完成类和对象的办法类似,这就是为何C++/CLI能够完成.NETCLI不撑持而C++撑持的言语特征,比方多重承继等的实质缘故原由。C++/CLI的实质能够借用一句话来讲明:
“.NET的回.NET,C++的还回C++!”
关于C++中类和对象的完成办法,还能够拜见《深度探究C++对象模子》一书(《InsideTheC++ObjectModel》一书的中译本)。
来自:http://blog.csdn.net/Changjiang/archive/2006/11/27/1415972.aspx
可怜的程序员,还是逃不出移植的命运!
作者:
谁可相欹
时间:
2015-1-21 09:12
最强的技术支持WebService,而且有.NET的所有library做后盾。而且ASP.NET在.NET3.5中还有微软专门为AJAX开发的功能--ASP.NETAJAX。
作者:
金色的骷髅
时间:
2015-1-30 13:06
众所周知,Windows以易用而出名,也因此占据不少的服务器市场。
作者:
小魔女
时间:
2015-2-6 01:04
是目前ASP在UNIX/Linux上的应用可以说几乎为0)。所以平台的局限性和ASP自身的安全性限制了ASP的广泛应用。
作者:
第二个灵魂
时间:
2015-2-14 19:29
CGI程序在运行的时候,首先是客户向服务器上的CGI程序发送一个请求,服务器接收到客户的请求后,就会打开一个新的Process(进程)来执行CGI程序,处理客户的请求。CGI程序最后将执行的结果(HTML页面代码)传回给客户。
作者:
仓酷云
时间:
2015-2-20 18:38
Servlet却在响应第一个请求的时候被载入,一旦Servlet被载入,便处于已执行状态。对于以后其他用户的请求,它并不打开进程,而是打开一个线程(Thread),将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程(ParentThread)来实现资源共享,这样就减轻了服务器的负担,所以,JavaServlet可以用来做大规模的应用服务。
作者:
愤怒的大鸟
时间:
2015-2-27 00:52
可以通过在现有ASP应用程序中逐渐添加ASP.NET功能,随时增强ASP应用程序的功能。ASP.NET是一个已编译的、基于.NET的环境,可以用任何与.NET兼容的语言(包括VisualBasic.NET、C#和JScript.NET.)创作应用程序。另外,任何ASP.NET应用程序都可以使用整个.NETFramework。开发人员可以方便地获得这些技术的优点,其中包括托管的公共语言运行库环境、类型安全、继承等等。
作者:
蒙在股里
时间:
2015-3-8 16:26
是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以,在排除错误时,可以采取分段排除的方法(在可能出错的代码前后输出一些字符串,用字符串是否被输出来确定代码段从哪里开始出错)。
作者:
精灵巫婆
时间:
2015-3-9 09:12
ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。
作者:
透明
时间:
2015-3-11 13:10
现在主流的网站开发语言无外乎asp、php、asp.net、jsp等。
作者:
admin
时间:
2015-3-18 11:57
ASP.NET可以无缝地与WYSIWYGHTML编辑器和其他编程工具(包括MicrosoftVisualStudio.NET)一起工作。这不仅使得Web开发更加方便,而且还能提供这些工具必须提供的所有优点,包括开发人员可以用来将服务器控件拖放到Web页的GUI和完全集成的调试支持。微软为ASP.net设计了这样一些策略:易于写出结构清晰的代码、代码易于重用和共享、可用编译类语言编写等等,目的是让程序员更容易开发出Web应用,满足计算向Web转移的战略需要。
作者:
飘飘悠悠
时间:
2015-3-25 18:53
由于JSP/Servlet都是基于Java的,所以它们也有Java语言的最大优点——平台无关性,也就是所谓的“一次编写,随处运行(WORA–WriteOnce,RunAnywhere)”。除了这个优点,JSP/Servlet的效率以及安全性也是相当惊人的。
作者:
冷月葬花魂
时间:
2015-3-27 10:10
Asp.net:首先来说,Asp.net和Asp没什么关系,看着像是升级版本什么的,其实没什么联系。Asp是脚本编程,用的是ASP语言,而ASP.net用的是C#语言,完全不同的东西。
作者:
深爱那片海
时间:
2015-4-1 15:57
市场决定一切,我个人从经历上觉得两者至少在很长时间内还是要共存下去,包括C和C++,至少从找工作就看得出来,总不可能大家都像所谓的时尚一样,追捧一门语言并应用它。
作者:
若相依
时间:
2015-4-3 05:13
是目前ASP在UNIX/Linux上的应用可以说几乎为0)。所以平台的局限性和ASP自身的安全性限制了ASP的广泛应用。
作者:
活着的死人
时间:
2015-4-4 18:07
平台无关性是PHP的最大优点,但是在优点的背后,还是有一些小小的缺点的。如果在PHP中不使用ODBC,而用其自带的数据库函数(这样的效率要比使用ODBC高)来连接数据库的话,使用不同的数据库,PHP的函数名不能统一。这样,使得程序的移植变得有些麻烦。不过,作为目前应用最为广泛的一种后台语言,PHP的优点还是异常明显的。
作者:
小妖女
时间:
2015-4-10 13:23
是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以,在排除错误时,可以采取分段排除的方法(在可能出错的代码前后输出一些字符串,用字符串是否被输出来确定代码段从哪里开始出错)。
作者:
若天明
时间:
2015-4-14 16:11
关于ASP.NET功能上,ASP.NET比微软以前的ASP(96年出现)有更强大的library,更好的稳定性。ASP.NET可以使用.NETFramework中所有组件(也就是说.NET能实现的,ASP.NET一样能实现)。
作者:
小女巫
时间:
2015-4-14 19:55
是指转换后的Servlet程序代码的行数。这给调试代码带来一定困难。所以,在排除错误时,可以采取分段排除的方法(在可能出错的代码前后输出一些字符串,用字符串是否被输出来确定代码段从哪里开始出错)。
作者:
因胸联盟
时间:
2015-4-27 10:58
可以通过在现有ASP应用程序中逐渐添加ASP.NET功能,随时增强ASP应用程序的功能。ASP.NET是一个已编译的、基于.NET的环境,可以用任何与.NET兼容的语言(包括VisualBasic.NET、C#和JScript.NET.)创作应用程序。另外,任何ASP.NET应用程序都可以使用整个.NETFramework。开发人员可以方便地获得这些技术的优点,其中包括托管的公共语言运行库环境、类型安全、继承等等。
欢迎光临 仓酷云 (http://ckuyun.com/)
Powered by Discuz! X3.2