最近学习了一段时间设计模式,慢慢意识到继承与组合,接口,多态的重要作用,因此又准备学习一下这方面理论知识,但是c++与c#有一些不同,时刻困扰着我,缠不清楚的感觉让人不舒服,于是自己总结了一下。
首先是类的实例化
c++中声明了 一个类的对象后 没有用类似于 C# 或 Java中的new 来实例化(刚开始我很费解),先看c#,类型按下图分类
C#的所有值类型均隐式派生自System.ValueType:
- 结构体:struct(直接派生于System.ValueType);
- 数值类型:
- 整 型:sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long (System.Int64),byte(System.Byte),ushort(System.UInt16),uint (System.UInt32),ulong(System.UInt64),char(System.Char);
- 浮点型:float(System.Single),double(System.Double);
- 用于财务计算的高精度decimal型:decimal(System.Decimal)。
- bool型:bool(System.Boolean的别名);
- 用户定义的结构体(派生于System.ValueType)。
- 数值类型:
- 枚举:enum(派生于System.Enum);
- 可空类型(派生于System.Nullable<T>泛型结构体,T?实际上是System.Nullable<T>的别名)。
值类型(Value Type),值类型实例通常分配在线程的栈(stack)上,并且不包含任何指向实例数据的指针,因为变量本身就包含了其实例数据
C#有以下一些引用类型:
- 数组(派生于System.Array)
- 用户用定义的以下类型:
- 类:class(派生于System.Object);
- 接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。Anders在《C# Programming Language》中说,接口只是表示一种约定[contract]);
- 委托:delegate(派生于System.Delegate)。
- object(System.Object的别名);
- 字符串:string(System.String的别名)。
可以看出:
- 引用类型与值类型相同的是,结构体也可以实现接口;
- 引用类型可以派生出新的类型,而值类型不能;
- 引用类型可以包含null值,值类型不能(可空类型功能允许将 null 赋给值类型);
- 引用类型变量的赋值只复制对对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值,也就是堆上保存着实例化对象,栈上保存着引用。
再看看,c++
我找资料发现c++中累的实例化有两种
A a;
A * a = new a();
以上两种方式皆可实现类的实例化,有new的区别在于:
1.前者在堆栈中分配内存,后者为动态内存分配,在一般应用中是没有什么区别的,但动态内存分配会使对象的可控性增强。
2.不加new在堆栈中分配内存
3.大程序用new,小程序直接申请
4.只是把对象分配在堆栈内存中
5.new必须delete删除,不用new系统会自动回收内存
看完第一点,大家应该明白了,其不同之处就在于c++与c#的栈不同,再考虑深层次原因,由于c#(java也类似,用的java虚拟机)程序是CLR负责垃圾的释放,栈操作只需要函数执行完就可以,它里面不存在所谓的垃圾,因此所谓的垃圾主要是指堆中内容,由于CLR有一套自己的回收机制,因此只要是稍微大一点的实例化对象就都放在了堆里,这样便于管理。c++不同,他需要用户手动释放,所以只要不是用户主动申请的,都必须放在栈里,才能够自动释放,除非用户主动申请,才把实例化对象放在堆里,这样用户也必须手动delete。