首先我们应该了解下什么是
浅拷贝:只复制对象的基本类型,对象类型,仍属于原来的引用
深拷贝:不仅复制对象的基本类,同时也复制原来对象中的对象
C#中有两种类型变量,一种是值类型变量,一种是引用类型便利那个,对于值类型便利那个,深拷贝和浅拷贝都是通过复制操作实现的,其效果是一样的,将对象中的值类型的字段拷贝到新的对象中。这个很容易理解。本文重点讨论引用类型变量的拷贝机制和实现。
为是上面说到的俩种。
浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用字段则指复制它的一个额饮用到目标对象
注意: string类型有点特殊,对于浅拷贝,按类值类型对象进行处理。
浅拷贝的实现
1 使用Ojbect类MemberwiseClone实现
MemberwiseClone:创建当前Object的浅拷贝副本
MemberwiseClone方法创建一个浅表副本,方式是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制,如果该字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一个对象。
示例代码:
public class Person { public int Age { get; set; } public string Address { get; set; } public Name Name { get; set; } public object Clone() { return this.MemberwiseClone(); } } public class Name { public Name(string frisName,string lastName) { FristName = frisName; LastName = lastName; } public string FristName { get; set; } public string LastName { get; set; } }
2 复制操作与使用Object类MemberwiseClone实现
对于引用类型的变量,我们有种误解,认为复制操作就是一种浅拷贝,其实是有区别的。
1浅拷贝对于引用类型对象中的值类型字段进行了逐位复制。赋值运算符只是把源对象的引用赋值给目的对象,两者引用同一个对象。
2浅拷贝后的对象的值类型字段更改不会反映到源对象,而赋值运算后的对象类型字段更改会反映到源对象。
==================================
深拷贝的实现
相对于浅拷贝是指依照源对象为原型,创建一个新对象,将当前对象的所有字段进行执行逐位复制并支持递归,不管是值类型还是引用类型,不管是静态字段还是非静态字段。
在C#中,我们有
1实现ICloneable接口,自定义拷贝功能
ICloneable接口包含一个成员Clone,以用于支持除
精灵是游戏的主角,我们在游戏中经常看到各种炫丽的精灵动画效果,之前我们提到精灵是由图片生成的,如果我们想要实现精灵的动画效果,比如捕鱼达人中摇尾游戏动的小鱼,就需要我们用很多张图片来生成一个个纹理,然后使纹理生成一个个的帧,再将这一个个的帧生成一个动画,额,说得有点乱,看代码会比较明白;
首先自定义一个精灵类fishSprite
fishSprite.h
#import <Foundation/Foundation.h> #import "cocos2d.h" @interface fishSprite : CCSprite { } +(id)fish; @end
fishSprite.m
@implementation fishSprite +(id)fish { return [[self alloc]initWithImage]; } -(id)initWithImage { if ((self=[super initWithFile:@"fish1.png"])) { NSMutableArray* frames = [NSMutableArray arrayWithCapacity:18]; //生成一个18的Array; for (int i = 1; i < 19; i++) { NSString *pngFile = [NSString stringWithFormat:@"fish%d.png",i]; //利用已知图片名生成纹理; CCTexture2D *texture = [[CCTextureCache sharedTextureCache]addImage:pngFile]; //利用纹理生成组成动画的帧; CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(0, 0, texture.contentSize.width, texture.contentSize.height)]; //将生成的帧添加到数组中,共18个,之后我们要用这18个frame来构成动画; [frames addObject:frame]; } //利用帧数组生成一个动画,设定帧与帧之间的切换频率为0.05; CCAnimation *animation =[CCAnimation animationWithSpriteFrames:frames delay:0.05]; //用CCAnimate将生成的CCAnimation转成可以用精灵操作的动作action: CCAnimate *animate = [CCAnimate actionWithAnimation:animation]; //设置为repeat CCRepeatForever *repeat = [CCRepeatForever actionWithAction:animate]; //执行 [self runAction:repeat]; //这样,如果该精灵一被实例化成功,就会动起来; } return self; } @end
修改模板自动生成的IntroLayer
IntroLayer.h
#import "cocos2d.h" #import "fishSprite.h" // HelloWorldLayer @interface IntroLayer : CCLayer { } // returns a CCScene that contains the HelloWorldLayer as the only child +(CCScene *) scene; @end
IntroLayer.m
#import "IntroLayer.h" #pragma mark - IntroLayer // HelloWorldLayer implementation @implementation IntroLayer // Helper class method that creates a Scene with the HelloWorldLayer as the only child. +(CCScene *) scene { // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. IntroLayer *layer = [IntroLayer node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene; } // -(void) onEnter//在载入该节点时被调用,有可能被调有多次; { [super onEnter]; // ask director for the window size CGSize size = [[CCDirector sharedDirector] winSize]; CCSprite *background; background = [CCSprite spriteWithFile:@"bg.jpg"]; background.position = ccp(size.width/2, size.height/2); // add the label as a child to this Layer [self addChild: background]; //在层上添加精灵; fishSprite *fish = [fishSprite fish]; fish.position = ccp(160,120); [self addChild:fish]; } @end
至于自动生成的helloWorld类直接删掉,这里不用它;另外,我们在工程里还需要添加组成帧动画的一个一个图片,如图所示;
这样运行后就可以看到一个不停运动的精灵,该精灵被创建后就是一个不断运动的效果,只需要指定位置,就会在指定的位置显示(图片不显示动画,懒得做gif了,亲们理解下啊),最后大家自己看下代码自己实现下,很简单的;
by zxy,Java/C++编程交流群:168424095
(36)有些人曾遇到if分支语句不执行的错误,例如:判断一个int型变量是否在2和10之间,以下写法是错误的if (2 < i <10){
}else{
}
关系操作符(<、<=、>、<=)具有左结合特性。事实上,由于关系操作符返回bool 类型的结果,很少使用其左结合特性。上式10大于1值为true和i值没有关系。这是因为第二个小于操作符的左操作数是第一个小于操作符的结果:true 或 false。也就是,该条件将10与整数0或1做比较。为了实现我们想要的条件检验,应重写上述表达式如下:if (2 < i && i < 10) { /* ... */ }
结论:不应该串接使用关系操作符
(37)如果某个数字常量以“0”开头(单纯的数字0除外),那么编译器会认为这是一个8进制数字(38)error C2065: “CString”: 未声明的标识符
包含#include <afx.h>头文件,且右键选择工程->属性->配置属性->常规->MFC的使用改为:在静态库中使用 MFC,否则编译出现下面的错误信息。
c:\program files\microsoft visual studio9.0\vc\atlmfc\include\afx.h(24) : fatal error C1189: #error : Building MFC application with /MD[d] (CRT dllversion) requires MFC shared dll version. Please #define _AFXDLL or do not use/MD[d]
(39)为了兼容性最好将for语句头的名字定义在for语句外面,否则会造成在有的情况下编译通不过。即:for(int i = 0;i <10; ++i)最好写成
int i =0;
for(i =0;i < 10; ++i)
因为在标准化之前的C++中,定义在for语句头的名字在for循环外是可以访问的。而标准化之后是不可以的。
(40)fatal error C1083: 无法打开包括文件:“iostream.h”: No such file or directory改为#include <iostream>