面向对象设计还需要表针吗?
大三的时候还在做单片机设计和MFC,玩纯C系语言表达,每天和表针相处,一切都是表针。有一天,听说JAVA里没有表针,我惊恐万状,没有表针,这种语言表达还能做什么?
之后,JAVA最先进的面向对象语言使用了更多类似C#的语言。相反,高端面向对象的语言没有表针,是好是坏?这些差异体现在哪里?本文从C#和C开始 对比一下,JAVA系统类似于C#。与大家深入探讨。
为了简单起见,我们首先定义了一个Point, 仅有X,Y 2个自变量。看一下C 与C#之间的应用差异
1. 表针和引入
C 表针和提到的有一定的区别,表针是一个详细的地址,而引入只是别称,引入使用起来要方便得多。由于表针本身是一个详细的地址,详细的地址可以完全偏向于每个地方,所以有一个指针,如果它与二维数组、函数公式、结构和类相关,它只是磨练人类的大脑。 C 重新定义的介绍必须在申报时复位,不能更改。
C#只有引入,所有的“引入自变量”都是引入。但是这个介绍和C 不同的介绍更像是一个“详细地址”。假如你申明了 Point p, 引入p就是引入。但是这个p很可能没有初始化,你可以随时改变它。
评价: 表针本来是个好东西,但是太灵便了,很复杂。总之,我现在不太喜欢看*和&这个标记。
2.类结构
C 自变量可以以两种形式建立:
(1) Point p, 您还结构了Point自变量。 它位于栈区。
(2) Point* p=new Point; 它在堆区:
最牛的取决于,Point points[10]; 在栈区,这一声明将直接导致十个Point目标。
也可以这样定义,Point* ps=new Point[10]; 处在堆区。
C#只有一种方法可以建立:Point p=new Point(); 处在堆区。
3. 互换2个目标
每个人都不能忘记,入门C 经典数据交换问题。
C 中, 二种作法: void Swap(int* a,int *b) 或者 void Swap(int& a,int& b) ,没什么好说的
有趣的是,如果交换两个目标呢? 假如是void Swap(Point a, Point b),这是错误的。在实施此函数时,复制构造函数将将您的实参复制到a和b2个对象中,并处于堆区。当函数公式返回时,你的目标仍然是原始的对象,除了浪费很多时间进行无意义的复制。 因而绝对是 void Swap(Point* a, Point *b)或是 void Swap(Point& a, Point& b)。
C#void可用于交换值类型 Swap(ref int a, ref int b), 如果是引用类型,直接使用void Swap(Point a, Point b)就可以了。
评价:你会发现,C 没有值类型和引用类型,加上*,&是“引用类型”,否则是值类型,值类型传输,将使用复制结构函数,造成一定的特性损害。而且C#不会有这种情况。
4.函数返回值和工厂模式
在程序设计模式的结构模式下,加工厂更为常见,你可以很容易地写一个C#版本的加工厂,但C 如何实现加工厂?
Point GetProduct(){
Point p; //设置为初始值。
returnp;
}
启用时 Point *p= &GetProduct();
你觉得这样对吗?交给读者讨论。
5.复制与对象的类组成
类可以组成,也可以继承。但C 考虑到以下结构,类组合会带来额外的问题:
classPointEx{
public:
Point A;
Point B;
///别人分析函数
}
也许你申请了Pointex pex, 这样,A、B2的目标就会全自动设定。如果要将A、B2类的主要参数传输到对象中,则必须应用“内部结构目标对象” 教材内容。而目标复制,也会带来额外的安全风险,默认复制结构函数只复制一般类型,但这些组合成员,如果直接=,那么两个Pointex估计偏向于同一个Point A。
在C#中,没有这样的问题。首先,A和B在Pointex的结构中根本不会被结构。假如你在Pointex中显式new出A和B。
此外,C 其中,衍生和父类的结构函数和分析函数的执行顺序尤为重要。C#在中间,以Dispose的方式取消了分析函数(因为GC)。
6. 函数指针和授权委托
首先,由于存储分为堆栈、堆栈、编码区和全局数据区,函数指针的战斗力非常强大。因此,表针用户可以访问编码区域,因此函数指针偏向编码区域,函数公式步骤可以偏向该区域。这也是函数指针的本质。
C 中:你可以这样定义函数指针 int (*sqrt) (int x); (看到真恶心,还没看到函数公式指针数组,回到函数指针函数等疯狂类型) 。这样取值:
先随意定义函数sqrt2, 然后func= sqrt2;就行了,
C#中:委托要这样定义 delegate int sqrt(int x); 取值相近。 此外,还有更强大的“事情”,完成了多播授权委托(我称之为授权二维数组)
评价: 委托的最大好处是类型强,看起来比函数指针优雅得多,效果也更强。
最近,我意识到了面向对象的巨大编程。假如能意识到“函数公式都是自变量”,那就是一个很大的发展。
7. 表针数据转换
先说一般值类型的表针数据转换。
C 中:定义两个表针, int*a 和float*b . 二是不能直接取值。若要取值,只能用空指针作为中介公司:
void*pv= a;b= static_cast
假如是目标,而且是有继承关系的,比如Point3D继承于Point,那么如何从Point*转变为Point3D*呢?
C#可采用强制类型转换或as关键词:
Point3D p3d= (Point3D)p2d; 或者 Point3D p3d= p2d as Point3D;
评价:形式是所有语言中非常复杂的一部分。 C#有强大的多类型系统和元数据库系统,操作更好。 但是,我有一个问题,C 在哪些地区存储变量类型?如何判断某一区域的内存是int而不是double? 编码区是否保存?
8. 类别与建筑结构的差异
C 在中国,类别和建筑结构基本上没有区别。建筑结构还可以定义函数,定义不同类型的自变量组成员,只有所有成员都公开发布;类别有密钥管理,可以实现继承和衍生。
C#类型为引用类型,建筑结构为值类型。建筑结构作为主要参数或传参,需要复制。此外,除对象外,建筑结构无法定义友元函数。使用建筑结构,将获得比类更高的特性。
造成这些差异的原因:内存分配
其实说了这么多,导致C#和C# 的 这种差异的本质原因取决于其内存分配系统的不同。
C 在中间,无论是目标还是普通值,如果是由 Point 如果形成p这种词法,那就在栈上。函数公式一旦完成,栈就会被回收利用。只有new关键字产生的目标,才能放入堆中。
堆栈上的数据需要如此复杂的表针系统,因为它们可以随时回收。表针地址问题,就像装小盒子一样。一个盒子不安全,只有几个多层的小盒子。小盒子越来越大,越来越复杂。
C#在中间,有值类型和引用类型的区别。所有引用类型都在堆中,回收利用由GC解决。一般函数中定义的值类型都在栈上。假如是目标中的“值”,那肯定也是定义在堆里的。因为堆比堆栈容易多了,所以只需要一个详细的地址。而且使用起来比在栈上方便多了。
说到特点,自然是栈比堆快,与内存用户访问集中有关。栈的信息基本都在计算机内存中,准确率很高。但堆不一定。 正是因为GC的功效,允许引用类型定义在堆中。自然,我坚信,在编译程序或操作中,C#的语言表达应该是数据库访问网络的热点,以优化准确性。 C#这种程序设计语言依赖于强大的“操作”(runtime)帮助VM虚拟机实现这种差异。
我还不太清楚堆栈和堆栈的比例是如何分配的。以前做单片机的时候,会有一个编译选项来选择它们的比例,我通常会把堆栈内存(heap)拖到90%,我不想用堆,因为我觉得麻烦。
那么,高端面向对象语言必须表针吗?
有了上面的段落,很多人可能会有结果。因为它适用于强大的操作,而且有垃圾回收器,所以堆的利用率比堆栈大得多。虽然特征有一点损害,但确实带来了简单高效的程序代码,程序猿不再需要玩表针游戏。它增加了以下好处:
1. 跳过复制构造函数和分析函数
2. 对函数的参数和传参进行了优化,无需再次启用复制函数公式,特性得到了提高。
3. 优化了目标组合的多样性,C 代码优化已经足够复杂了,面向对象的编程会变得更加复杂。如果不注意,很容易出现内存泄漏和表针悬架。但在C#中,您可以放心大胆地应用组成和继承。战略要清楚得多。
4.C#,JAVA编码漂亮多了,至少没有那些奇怪的符号。
5. 我还没有想到其他的好处。
从这个角度来看,表针的功效早已被“引入”类型所取代。
可是,C 无需操作中和VM虚拟机,立即将程序编译为原始代码,无疑具有更强的特性,但确实是C 难懂。C 大神当然可以列举一堆C 运行内存系统的好处是不同的。