Object Pascal:从对象指针谈起 正在热烈讨论,欢迎大家参与,提出自己的见解。也希望给大家一些启发。敬请关注《Object Pascal:从对象指针谈起》,参与讨论。http://www.csdn.net/develop/article/10/10124.shtm 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 **********************Nicrosoft (2001-8-28 23:39:08) Form := TForm(Obj);ShowMessage(TButton(I).Caption);向上映射不好吧...还有,其实VCL对象使用的是引用/值模型,严格来说,并不是指针,因为我们引用对象方法时,是这样:Form1.Show();而不是Form1^.Show();********************* Musicwind (2001-8-29 10:50:23) to NicroSoft: 谢谢你参与讨论。 对于你说的"向上映射不好吧...",我赞同。因为文章里讨论的其实只是表示一种技术上的可能,但并不表示就推荐这么做。谢谢你的意见。 对于你说的“引用/值模型”,本人第一次听说,真是惭愧。但是我还是坚持认为Form1的的确确是一个指针,不能因为访问的时候可以不加^就不是指针,那其实只是Delphi帮助你省略掉了。假如有如下的代码:var Form1: TForm1; Form2: ^TForm1;implementation{$R *.dfm}procedure TForm1.MusicBtn1Click(Sender: TObject);begin Form2 := @Form1; ShowMessage(Form2^.Caption);end;难道因为"Form2^.Caption"这样的语句就承认Form2是一个指针,而不承认Form1么?其实,Form1是指针,Form2同样也是指针,只是Form2是指向指针的指针而已。 不知NicroSoft兄是否有些同意我的看法? 谢谢讨论。*************************chechy (2001-8-29 12:02:47) 我赞成Musicwind的观点。向上映射没什么不好。实际上再Delphi中,每个控件都有一个Tag属性,活用这个Tag属性可以节省大量的代码。而这个Tag刚好是整形,4个字节。这就意味着它能够存贮指针。不过我更愿意把所谓的对象指针称之为Reference类型。这个概念和Java类似。指针这个东西,我一直觉得它的名字起的不好,如果从物理的角度去理解,可能会有更好的感觉。即从Address的角度去理解,而不是将它想象为Pointer。另Musicwind,第3节是面向对象的特性,不是指针的特性。**********************Nicrosoft (2001-8-29 12:28:24) to Musicwind:var Form1: TForm1; Form2: ^TForm1;implementation{$R *.dfm}procedure TForm1.MusicBtn1Click(Sender: TObject);begin Form2 := @Form1; ShowMessage(Form2^.Caption);end;对于这个代码,我只能说,Form1是引用,Form2是指针。所谓引用,就是对象的别名,也就是可以当作对象来使用的“奇异”的指针,Form1就是这样的,Form2^.Caption说明了它才是指针(BTW,好像老兄比较关注我的文章哦,我写了一篇,你就会有相应的文章出现,哈哈,个人感觉而已,不知道对不对)to chechy:我说的向上映射不好,是说这样的映射是“不安全”的。所以编译器需要程序员强制类型转换以确认这样做的后果。面向对象编程的思想中,这样的做法是不被推荐的。*******************************Nicrosoft (2001-8-29 12:30:05) 另外,Delphi是基于“引用/值模型”的说法,不是我说的,而是Charlie说的。******************************chechy (2001-8-29 12:47:03) 向上映射是存在不安全性。不过实际应用应该非常广泛的。我记得Nicrosoft你好像写过有关数据与界面分离的文章(大概是这个意思)。实际上我在写一些底层模块时,通常只用TObject,TForm,TComponent这样的基类。而在实际过程中,这些都是具体的对象,那么就需要被转化。此外Delphi的Uses不能循环使用,也迫使某些参数必须使用基类。这些都是向上映射。不过在转化是,我倒是建议大家不要使用强制类型转换,而用as操作符。虽然效率差了些,但是对于发现程序错误非常有用。***************************************Musicwind (2001-8-29 13:09:51) to chechy: 很高兴再一次见到你回复我的贴字,谢谢! 对你所说的活用Tag,表示赞同!因为这其实是我第四节隐含在文字后面想要表达的意思。 不用"指针",而用reference似乎也说得过去。 至于第三节,有些面向对象的特性,说得好。 to hellion(恶人): 说得好,正有此嫌疑。 to Musicwind:虽然引用的本质是指针,但是,对于程序员来说,他们的概念还是需要清晰的区分的引用对于程序员来说,可以看作对象本身,而指针不是。你的第二个例子中:PRPerson = ^TRPerson;pPerson: PRPerson;已经承认了,它是指针但是如果这样定义:pPerson: TRPerson; 这样就不是指针,而是声明一个引用了是指针还是引用,不是看调用的地方有没有^,而是看声明的地方。调用的地方可以省略^,只是编译器的特性,却不是语言的特性。 to NicroSoft: 有些说到正题上了。 你说 "rPerson: TRPerson; "的声明是引用,并且认为"Form1: TForm1"的声明也是引用,我觉得你是自相矛盾的。 请问,既然都是引用,那么,为什么系统自动分配一个TRPerson记录的内存给rPerson而不需要调用new或者Alloc等函数?为什么声明Form1的时候,系统只是分配作为指针所需的内存而已,并没有分配创建一个TForm1所需的内存?为什么我们可以直接使用rPerson.Name而对于Form1.Name我们需要事先调用TForm1.Create(...)呢?同是引用,有这么大的区别么? 请注意:"Form1: TForm1;"的声明和"rPerson: TRPerson;"截然不同。 rPerson和Form1只能有一个是引用,你选择哪个? 请回复,答疑,解惑。 我有些糊涂呵不过我也同意Form1为一指针因为对于VCL类,只能在堆中生成,我们动态建一窗口Form1 := TForm1.Create(self)这种行为更像指针在c++builder中为Form1 := new TForm1(this);而对于引用我觉得变量参数是为引用吧Show(var i: Integer);正如C++中的Show(int& i);我是瞎说的欧,呵呵 to Musicwind:你不知道“结构”(pascal称为“记录”)和“类”的区别吗?我也有错的,应该这样说,rPerson : TRPerson定义的是一个记录类型的实体,而不是引用,它是值!而Form1 : TForm1声明的是一个引用。这就是所谓的“引用/值”模型。对于简单类型/内建类型,编译器以值模型来使用对象,对于“类”类型的对象,编译器以“引用”模型使用对象。声明结构本身就是定义了一个实体,但是类呢?类是“活”的,因此需要创建。这还得提到vcl的对象模型。vcl的所有对象是建立在“堆”上的,因此,所有的“类”类型的对象必须通过.Create来创建,Free来释放。而简单类型的对象不需要,他们是创建在“栈”上的,因此一旦声明,就有了实体,并在超出作用域后会被编译器释放其空间。不过,object pascal的引用和c++的引用还是有区别的。c++的引用不允许空引用,不允许动态改变引用所指向的对象,但是,object pascal的引用允许。因为object pascal的对象只能建立在堆上。 to NicroSoft: 对于结构和类的区别吗,我还是知道一点地,我那番话,至少可以反驳你说"rPerson: TRPerson"是引用的那个观点。 好了,吵归吵,你的许多观点对我还是受益匪浅。经过我一番恐吓,抢白,你终于不吝笔墨把有关"引用/值"的模型阐述了一下,谢谢。 在C++中声明一个类的时候和Delhi的大不相同,同意。 to xzgyb(回首往事,不堪回首): 啊呀呀!英雄所见略同呀! 引用/值是不是Reference/Value的翻译。如果这样,我也同意类对象是Reference而不是Pointer。因为类对象本质上确实是指针,但是从外表看却不像指针调用。(标准的Pascal指针调用必须是P^.Name := 'hello, world';)类比其他语言:如Java,Java没有指针,它的类和Delphi类似,也需要new一下,才能创建。Java把它们称之为Reference。再比如C#,虽然它也有指针,和C++一样,需要中规中举的用->操作符。但是它的类使用却和Java相同,也是Reference类型。所以我觉得Reference根据贴切。 to chechy: 你是一面旗帜! to chechy:赞同你说的那一段关于"引用/值"模型 To Musicwind:千万别这么说。你那样说我,我真得找个洞钻进去了。呵呵... 再看一遍 xzgyb(回首往事,不堪回首) 的发言,很有些道理呀。 Musicwind老大,我存属瞎说的,呵呵, Just Push, want people to discuss ! qinghou (2001-8-30 22:49:24) 呵呵,很少见到对Object Pascal这么深入的讨论个人观点:1、在OP中,向上映射没有什么不好,正好相反,向上映射是OP的优点之一。Form := TForm(Obj);这种语法确实有危险,比较安全的用法应该是If Obj is TForm Then Form := TForm(Obj);as和is操作符是OP优于C++的地方之一,因为OP的单根结构,使它对RTTI有非常好的支持。想想看,在Delphi的事件处理过程中,往往都是传进来一个TObject类型的Sender对象,如果不对它进行向上映射,那么这个Sender就一点用都没有了。2、我赞成Musicwind的观点,Form1: TForm1;这种形式,与其说Form1是一个引用,不如说它是一个指针。OP确实是建立在“对象引用模型”或者说“对象/值模型”(应该是译名不同)之上,但是这种引用和C++的引用完全不同,它其实就是一种指针。在OP中,永远不能直接定义一个C++意义上的对象变量,当你定义一个对象变量时,事实上只是定义了一个地址,用以保存对象的内存位置。你必须手动create这个对象。当你访问对象时,事实上也是通过这个地址访问的。这个是大家都知道的。那么你到底将它视为指针还是引用呢?Nicrosoft说:“虽然引用的本质是指针,但是,对于程序员来说,他们的概念还是需要清晰的区分的引用对于程序员来说,可以看作对象本身,而指针不是。”这种区别在C++里是有意义的,但Delphi中就不同了。因为在Delphi中,没有哪种引用可以看作“对象本身”,甚至根本就没有“对象本身”。你用来用去的都是对象指针而已,只是没有显式地以指针方式表示出来。我甚至认为OP中根本没有C++中的引用这种概念。Nicrosoft认为OP和C++的引用的区别是:“c++的引用不允许空引用,不允许动态改变引用所指向的对象”那么,请想象一下,有这样一个变量,它存储着一个对象的地址,但这个地址可以为空,也可以动态改变指向的对象。你说它是象一个引用呢,还是象一个指针呢?Macro Cantu在《Delphi4从入门到精通》(中文版,P61)里曾经说到这种对象引用模型,描述如下:“它的基本思想是,一个类的每个变量,并不保存对象的值,而是保存一个引用,或一个指针,以来说明对象存储的内存位置。”“使用这种方法的唯一问题是,当声明一个变量时,我们不能在内存中建立一个对象,只是保存对象引用的内存地址——一种指针。”在这里,他是把引用和指针等同起来的。Macro Cantu认为对象引用模型是Delphi开发者所做的设计决定中最好的一个。我也觉得这种方式比C++更加清晰。 再次引述一下qinghou 提到的Macro Cantu的一番话:它的基本思想是,一个类的每个变量,并不保存对象的值,而是保存一个引用,或一个指针,以来说明对象存储的内存位置。”“使用这种方法的唯一问题是,当声明一个变量时,我们不能在内存中建立一个对象,只是保存对象引用的内存地址——一种指针。”很有见地,深刻! 我觉得争论到这里就没有意义了,你说保存对象都是指针,这是废话。但是我不是编译器的实现者,我不需要知道编译器如何实现保存对象的,我所关注的,只是对于程序员来说,引用和指针是有区别的,引用的确可以看作对象本身(对象的别名,见Mashall Cline的C++ FAQ Lite),而指针不是。不需要争论引用是如何实现的,我不管它是用指针实现的或者不是,我不管!也没有必要管! java没有指针,和这个类似的东西叫什么呢?——Reference是不是只有Object Pascal不支持指针的时侯,你才承认它是Reference呢? 很明显:var form1 : TForm1; form2 : ^Tform1;begin // some code to create form1 form2 := @Form1; ShowMessage(form2^.Caption); ShowMessage(form1.Catpion);end;form1和form2从定义就可以看出,他们是有很大区别的。非要说他们是一回事,那么只能说你概念不清,却要找借口——“引用是用指针实现的”至于,Form2.Caption也能编译通过,是纯粹的编译器特性,但是delphi并不等于Object Pascal!看定义,就非常清楚,那么的本质区别,一个用引用方式定义,一个用指针方式定义。 小弟,看到各位大虾的讨论,真是精辟,但是Musicwind和NICROSOFT的观点,不同from1:tform;那么FORM1是指针,还是引用,Musicwind说的很清楚,form1,只是一个,内存地址(这里先不说成指针)但这个地址,应该怎么称呼,我想NICROSOFT的话有一定道理form2^tfrom;这是指针,大家都知道(没有意见吧)Musicwind说,form1看成指针,那么form2就是指向form1的指针了,我不知道OP中,多重指针是什么样的,(我水平不高,是来灌水的)如果把,form1理解成,指针,是不是,真繁的,我想现在大家,都明白怎么回事,就是对于form1的类型,没有达成一致,当然我就更不能下结论了希望各位高手给个,结论好吗???? 发现这样也行procedure TForm1.Button6Click(Sender: TObject);type TTest = record ii, jj: Integer; end;var PTest: ^TTest; tmp: TTest;begin tmp.ii := 23; tmp.jj := 24; PTest := @tmp; ShowMessage(IntToStr(PTest.ii)); //不写PTest^.ii也行end; 其实,不管怎样理解,是不影响使用的。但是,正如byrybye所说,Musicwind如果把form1:TForm1理解为指向指针,那么form2:^TForm1就是指向指针的指针了,很难自圆其说。而我的说法,我想是很清晰的,概念清晰很重要,对于一个严谨的程序员来说当然,我不是说Musicwinde不严谨,但是在这个问题上,我觉得你概念不清。再强调一次,我们都不是编译器的实现者,因此没必要知道引用是如何实现的。 to xzgyb: 我希望你看看前面的帖子,你说的这种情况(即使用时可以省略^)是编译器的特性,它允许这样“偷懒”而已。但不是语言的特性。指针就是指针,对象就是对象,引用就是引用。看是否指针就看定义处。 再引用一段Mashall Cline对引用的描述吧:请不要将引用看作为指向一个对象的奇异指针,即使引用经常是用汇编语言下的地址来实现的。引用就是对象。不是指向对象的指针,也不是对象的拷贝,就是对象。 delphi 当然不是 Object Pascal!我可没说是哦。;)但是我们现在讨论的是Borland 版本的Object Pascal,请注意:不要将C++中的一些概念强加到Object Pascal里。其实已经很清楚了,在Object Pascal中,Form1: TForm1;这样的声明就是定义了一个指针,如果你非要说它是引用,当然也可以,那么引用和指针是等同的,至少在 Object Pascal(Borland版)中是如此。这就是结论。我想qinghou所引的那番话的确很有道理。Macro Cantu在《Delphi4从入门到精通》(中文版,P61)里曾经说到这种对象引用模型,描述如下:“它的基本思想是,一个类的每个变量,并不保存对象的值,而是保存一个引用,或一个指针,以来说明对象存储的内存位置。”“使用这种方法的唯一问题是,当声明一个变量时,我们不能在内存中建立一个对象,只是保存对象引用的内存地址——一种指针。”在这里,他是把引用和指针等同起来的。Macro Cantu认为对象引用模型是Delphi开发者所做的设计决定中最好的一个。这样做更加清晰,我也这么觉得。 首先,你并没有定下“只讨论Borland版本的OP”的前提!其次,引用概念并非只有OP中有,没有谁强加谁的问题!再次,引用<>(或者 !=) 指针最后,我不管borland如何实现引用,你不能做任何假设或断言,因为以后引用也可能不用指针来实现,我想你知道什么是“面向接口编程”吧 Macro是作为编译器的实现者来阐述这个问题的 欧,我原先以为只有TObject的派生类可以省略^ 像 Form1.Show而不用写成Form1^.Show而指向记录的指针也可以这么写 我也同意引用就是对象而我感觉用不用^,只是对pascal概念的一种体现,并不影响使用. form1就是个指针form1和form1^并没有区别,只是方便大家书写程序否则要是每个对象都要^,岂不是很累你甚至可以定义个Integer来保存form1a = integer(form1);等你那次需要的时候,就可以这么写form2 := TForm(a);然后用Form2 to NicroSoft: 对,生活就是折腾,没错。to byrybye: 结论由个人自己下吧,看来要想取得一致的看法很难了。 外部数据库驱动程序 (15877) 中的意外错误 一个关于传递变量的问题 如何把一个16进制常量写入某个文件 ARP包(监听、嗅探) 急,在线等待:高分求,已知一个*.QRP文件怎么用DELPHI文件打开它,并且可以跳出打印设置? 请问SQL中的Numeric相当于DELPHI中的那种Field.datatype? 关于图片的高技术问题! 一个算法,不知道怎么算 服务程序中 ADOConnection 无法连接数据库 300---注册表,被封了这么办--- 如何能让button一开始的时候就凹下去??? 使用delphi将一个最小化的窗口复原?
Nicrosoft (2001-8-28 23:39:08) Form := TForm(Obj);
ShowMessage(TButton(I).Caption);向上映射不好吧...还有,其实VCL对象使用的是引用/值模型,严格来说,并不是指针,因为我们引用对象方法时,是这样:
Form1.Show();
而不是
Form1^.Show();*********************
Musicwind (2001-8-29 10:50:23)
to NicroSoft:
谢谢你参与讨论。
对于你说的"向上映射不好吧...",我赞同。因为文章里讨论的其实只是表示一种技术上的可能,
但并不表示就推荐这么做。谢谢你的意见。
对于你说的“引用/值模型”,本人第一次听说,真是惭愧。但是我还是坚持认为Form1的的确确是
一个指针,不能因为访问的时候可以不加^就不是指针,那其实只是Delphi帮助你省略掉了。假如有如下
的代码:
var
Form1: TForm1;
Form2: ^TForm1;implementation{$R *.dfm}procedure TForm1.MusicBtn1Click(Sender: TObject);
begin
Form2 := @Form1;
ShowMessage(Form2^.Caption);
end;难道因为"Form2^.Caption"这样的语句就承认Form2是一个指针,而不承认Form1么?
其实,Form1是指针,Form2同样也是指针,只是Form2是指向指针的指针而已。 不知NicroSoft兄是否有些同意我的看法?
谢谢讨论。*************************
chechy (2001-8-29 12:02:47)
我赞成Musicwind的观点。向上映射没什么不好。实际上再Delphi中,每个控件都有一个Tag属性,活用这个Tag属性可以节省大量的代码。而这个Tag刚好是整形,4个字节。这就意味着它能够存贮指针。
不过我更愿意把所谓的对象指针称之为Reference类型。这个概念和Java类似。
指针这个东西,我一直觉得它的名字起的不好,如果从物理的角度去理解,可能会有更好的感觉。即从Address的角度去理解,而不是将它想象为Pointer。
另Musicwind,第3节是面向对象的特性,不是指针的特性。**********************
Nicrosoft (2001-8-29 12:28:24)
to Musicwind:var
Form1: TForm1;
Form2: ^TForm1;implementation{$R *.dfm}procedure TForm1.MusicBtn1Click(Sender: TObject);
begin
Form2 := @Form1;
ShowMessage(Form2^.Caption);
end;对于这个代码,我只能说,Form1是引用,Form2是指针。所谓引用,就是对象的别名,也就是可以当作对象来使用的“奇异”的指针,Form1就是这样的,Form2^.Caption说明了它才是指针(BTW,好像老兄比较关注我的文章哦,我写了一篇,你就会有相应的文章出现,哈哈,个人感觉而已,不知道对不对)to chechy:
我说的向上映射不好,是说这样的映射是“不安全”的。所以编译器需要程序员强制类型转换以确认这样做的后果。面向对象编程的思想中,这样的做法是不被推荐的。*******************************
Nicrosoft (2001-8-29 12:30:05)
另外,Delphi是基于“引用/值模型”的说法,不是我说的,而是Charlie说的。******************************
chechy (2001-8-29 12:47:03)
向上映射是存在不安全性。不过实际应用应该非常广泛的。我记得Nicrosoft你好像写过有关数据与界面分离的文章(大概是这个意思)。实际上我在写一些底层模块时,通常只用TObject,TForm,TComponent这样的基类。而在实际过程中,这些都是具体的对象,那么就需要被转化。此外Delphi的Uses不能循环使用,也迫使某些参数必须使用基类。这些都是向上映射。
不过在转化是,我倒是建议大家不要使用强制类型转换,而用as操作符。虽然效率差了些,但是对于发现程序错误非常有用。***************************************
Musicwind (2001-8-29 13:09:51)
to chechy:
很高兴再一次见到你回复我的贴字,谢谢!
对你所说的活用Tag,表示赞同!因为这其实是我第四节隐含在文字后面想要
表达的意思。
不用"指针",而用reference似乎也说得过去。
至于第三节,有些面向对象的特性,说得好。
说得好,正有此嫌疑。
PRPerson = ^TRPerson;
pPerson: PRPerson;
已经承认了,它是指针
但是如果这样定义:pPerson: TRPerson; 这样就不是指针,而是声明一个引用了是指针还是引用,不是看调用的地方有没有^,而是看声明的地方。调用的地方可以省略^,只是编译器的特性,却不是语言的特性。
有些说到正题上了。
你说 "rPerson: TRPerson; "的声明是引用,并且认为"Form1: TForm1"的声明也是引用,我觉得
你是自相矛盾的。
请问,既然都是引用,那么,为什么系统自动分配一个TRPerson记录的内存给rPerson而不需要调用
new或者Alloc等函数?为什么声明Form1的时候,系统只是分配作为指针所需的内存而已,并没有分配
创建一个TForm1所需的内存?为什么我们可以直接使用rPerson.Name而对于Form1.Name我们需要事先调用
TForm1.Create(...)呢?同是引用,有这么大的区别么?
请注意:"Form1: TForm1;"的声明和"rPerson: TRPerson;"截然不同。
rPerson和Form1只能有一个是引用,你选择哪个? 请回复,答疑,解惑。
不过我也同意Form1为一指针
因为对于VCL类,只能在堆中生成,我们动态建一窗口
Form1 := TForm1.Create(self)这种行为更像指针
在c++builder中为
Form1 := new TForm1(this);
而对于引用我觉得变量参数是为引用吧
Show(var i: Integer);
正如C++中的
Show(int& i);我是瞎说的欧,呵呵
声明结构本身就是定义了一个实体,但是类呢?类是“活”的,因此需要创建。
这还得提到vcl的对象模型。vcl的所有对象是建立在“堆”上的,因此,所有的“类”类型的对象必须通过.Create来创建,Free来释放。而简单类型的对象不需要,他们是创建在“栈”上的,因此一旦声明,就有了实体,并在超出作用域后会被编译器释放其空间。不过,object pascal的引用和c++的引用还是有区别的。c++的引用不允许空引用,不允许动态改变引用所指向的对象,但是,object pascal的引用允许。因为object pascal的对象只能建立在堆上。
对于结构和类的区别吗,我还是知道一点地,我那番话,至少可以反驳你说"rPerson: TRPerson"是引用的那个观点。
好了,吵归吵,你的许多观点对我还是受益匪浅。经过我一番恐吓,抢白,你终于不吝笔墨
把有关"引用/值"的模型阐述了一下,谢谢。
在C++中声明一个类的时候和Delhi的大不相同,同意。
啊呀呀!英雄所见略同呀!
因为类对象本质上确实是指针,但是从外表看却不像指针调用。(标准的Pascal指针调用必须是P^.Name := 'hello, world';)
类比其他语言:如Java,Java没有指针,它的类和Delphi类似,也需要new一下,才能创建。Java把它们称之为Reference。再比如C#,虽然它也有指针,和C++一样,需要中规中举的用->操作符。但是它的类使用却和Java相同,也是Reference类型。
所以我觉得Reference根据贴切。
你是一面旗帜!
千万别这么说。你那样说我,我真得找个洞钻进去了。呵呵...
呵呵,很少见到对Object Pascal这么深入的讨论
个人观点:
1、在OP中,向上映射没有什么不好,正好相反,向上映射是OP的优点之一。
Form := TForm(Obj);
这种语法确实有危险,比较安全的用法应该是
If Obj is TForm Then Form := TForm(Obj);
as和is操作符是OP优于C++的地方之一,因为OP的单根结构,使它对RTTI有非常好的支持。想想看,在Delphi的事件处理过程中,往往都是传进来一个TObject类型的Sender对象,如果不对它进行向上映射,那么这个Sender就一点用都没有了。
2、我赞成Musicwind的观点,Form1: TForm1;这种形式,与其说Form1是一个引用,不如说它是一个指针。OP确实是建立在“对象引用模型”或者说“对象/值模型”(应该是译名不同)之上,但是这种引用和C++的引用完全不同,它其实就是一种指针。
在OP中,永远不能直接定义一个C++意义上的对象变量,当你定义一个对象变量时,事实上只是定义了一个地址,用以保存对象的内存位置。你必须手动create这个对象。当你访问对象时,事实上也是通过这个地址访问的。这个是大家都知道的。那么你到底将它视为指针还是引用呢?
Nicrosoft说:
“虽然引用的本质是指针,但是,对于程序员来说,他们的概念还是需要清晰的区分的
引用对于程序员来说,可以看作对象本身,而指针不是。”
这种区别在C++里是有意义的,但Delphi中就不同了。因为在Delphi中,没有哪种引用可以看作“对象本身”,甚至根本就没有“对象本身”。你用来用去的都是对象指针而已,只是没有显式地以指针方式表示出来。我甚至认为OP中根本没有C++中的引用这种概念。
Nicrosoft认为OP和C++的引用的区别是:
“c++的引用不允许空引用,不允许动态改变引用所指向的对象”
那么,请想象一下,有这样一个变量,它存储着一个对象的地址,但这个地址可以为空,也可以动态改变指向的对象。你说它是象一个引用呢,还是象一个指针呢?
Macro Cantu在《Delphi4从入门到精通》(中文版,P61)里曾经说到这种对象引用模型,描述如下:“它的基本思想是,一个类的每个变量,并不保存对象的值,而是保存一个引用,或一个指针,以来说明对象存储的内存位置。”“使用这种方法的唯一问题是,当声明一个变量时,我们不能在内存中建立一个对象,只是保存对象引用的内存地址——一种指针。”在这里,他是把引用和指针等同起来的。
Macro Cantu认为对象引用模型是Delphi开发者所做的设计决定中最好的一个。我也觉得这种方式比C++更加清晰。
form2 : ^Tform1;
begin
// some code to create form1
form2 := @Form1;
ShowMessage(form2^.Caption);
ShowMessage(form1.Catpion);
end;form1和form2从定义就可以看出,他们是有很大区别的。非要说他们是一回事,那么只能说你概念不清,却要找借口——“引用是用指针实现的”至于,Form2.Caption也能编译通过,是纯粹的编译器特性,但是delphi并不等于Object Pascal!看定义,就非常清楚,那么的本质区别,一个用引用方式定义,一个用指针方式定义。
from1:tform;
那么FORM1是指针,还是引用,Musicwind说的很清楚,form1,只是一个,内存地址(
这里先不说成指针)但这个地址,应该怎么称呼,我想NICROSOFT的话有一定道理
form2^tfrom;这是指针,大家都知道(没有意见吧)
Musicwind说,form1看成指针,那么form2就是指向form1的指针了,我不知道
OP中,多重指针是什么样的,(我水平不高,是来灌水的)
如果把,form1理解成,指针,是不是,真繁的,我想现在大家,都明白
怎么回事,就是对于form1的类型,没有达成一致,当然我就更不能下结论了
希望各位高手给个,结论好吗????
procedure TForm1.Button6Click(Sender: TObject);
type
TTest = record
ii, jj: Integer;
end;
var
PTest: ^TTest;
tmp: TTest;
begin
tmp.ii := 23;
tmp.jj := 24;
PTest := @tmp;
ShowMessage(IntToStr(PTest.ii)); //不写PTest^.ii也行
end;
我可没说是哦。;)
但是我们现在讨论的是Borland 版本的Object Pascal,
请注意:不要将C++中的一些概念强加到Object Pascal里。
其实已经很清楚了,在Object Pascal中,Form1: TForm1;这样的声明就是定义了一个
指针,如果你非要说它是引用,当然也可以,那么引用和指针是等同的,至少在 Object Pascal
(Borland版)中是如此。
这就是结论。我想qinghou所引的那番话的确很有道理。
Macro Cantu在《Delphi4从入门到精通》(中文版,P61)里曾经说到这种对象引用模型,描述如下:“它的基本思想是,一个类的每个变量,并不保存对象的值,而是保存一个引用,或一个指针,以来说明对象存储的内存位置。”“使用这种方法的唯一问题是,当声明一个变量时,我们不能在内存中建立一个对象,只是保存对象引用的内存地址——一种指针。”在这里,他是把引用和指针等同起来的。
Macro Cantu认为对象引用模型是Delphi开发者所做的设计决定中最好的一个。这样做更加清晰,我也这么觉得。
而指向记录的指针也可以这么写
而我感觉用不用^,只是对pascal概念的一种体现,并不影响使用.
form1和form1^并没有区别,只是方便大家书写程序
否则要是每个对象都要^,岂不是很累
你甚至可以定义个Integer来保存form1
a = integer(form1);等你那次需要的时候,就可以这么写
form2 := TForm(a);
然后用Form2
对,生活就是折腾,没错。to byrybye:
结论由个人自己下吧,看来要想取得一致的看法很难了。