我在Unit1里面如下声明
TA =class(TObject)
private
a:string;
constructor create(s:string);
end;
注意两点,(1)create我声明成private的(2)后面没有用overload指示字,这会让其覆盖TObject那个默认Create现在在Unit1中写下代码
A:=TA.Create('s'); //OK
A:=TA.Create; //编译不通过
如上的情况我都能理解,问题在下面在Unit2中写下如下代码
A:=TA.Create; //编译通过,OK
为什么会出现这种情况?
TA =class(TObject)
private
a:string;
constructor create(s:string);
end;
注意两点,(1)create我声明成private的(2)后面没有用overload指示字,这会让其覆盖TObject那个默认Create现在在Unit1中写下代码
A:=TA.Create('s'); //OK
A:=TA.Create; //编译不通过
如上的情况我都能理解,问题在下面在Unit2中写下如下代码
A:=TA.Create; //编译通过,OK
为什么会出现这种情况?
解决方案 »
- MDI窗体
- 在DBGRID里面鼠标滚动时,如果让与数据库关联的DBEDIT的值也跟着变动.
- 解决马上给分:FindComponent方法报错!!
- 兄弟们帮帮忙阿,dbgrid
- bitmap 如何加载剪切板中的图片?
- 求做ocx的书籍
- Dev Express为Delphi 7 做的控件从哪儿可以下载?
- 用unidac的unitable手动连接firebird数据库 提示no permission for read select access to table
- DCOM调用 XP系统下提示“占位程序接收到错误数据”,2000下运行正常,急!!!!!!!!!
- delphi中使用自定义消息传送字符串的问题
- 求高手将一段c++builder代码转成delphi
- report builder 做报表生成PDF文件中文乱码?
以我的理解,那个默认的Create已经被带参数的Create覆盖掉了,所以在Unit1中看不到是对的,但是在Unit2中怎么又出来了?反而能看到了?太奇怪了啊
A:=TA.Create('s'); 这个能通过吗??
因为对UNIT2来说,UNIT1中的构造函数是不可见的。
----------------------------------------------------
Unit1中,将构造函数定义为private,那么,对于其他单元来说,你自己定义的constructor是不可见的.
因此,在Unit2中,调用constructor的Create时,编译器没有在public中找到你定义的constructor,于是,它就会去调用父类中去寻找constructor,然后去调用,就是TObject.Create.
在Unit1中,编译器明显看不到默认的那个Create,编译都不会通过。但是到了Unit2中,难道编译器由于找不到合适的Create,就开了天眼,重新去基类中找到了那个默认的Create?这样的编译器行为岂不是很怪异?
我一句A:=TA.Create;放在程序Unit2中编译能通过,Unit1中就编译通不过,实在让人沮丧。
为什么在Unit1中编译器不去找找那个默认的Create呢?
不用overload指示字,也就是明确我的Create会覆盖掉TObject的Create,编译器应该确定就是看不到基类的Create才对。而不是说看得到,但是我编译就是不让你通过,气死你。
但是真到了Unit2里面,编译器突然又能看到基类的Create了,编译又放行了。。
这样的逻辑应该是说不过去的呢,估计另有隐情,还求大牛继续解答。我觉得如果Unit2中A:=TA.Create编译能过,Unit1中没有道理编不过。要不就两个Unit都不支持,这才说得过去。
你可以做个测试,你在unit1中定义了一个函数Test,在unit2中同样定义了一个Test函数,unit1中引用unit2,那么如果你在unit1中调用Test,它只会找到unit1中的Test函数。如果unit1中没有定义Test函数,这时候它才会去其他单元找Test.
差不多就是这个意思。
它在TA中已经找到一个Create函数,那么,它就默认你调用的是这个Create,其他的一律不认。
另一个就是它的接口机制,有些混乱,和COM这种特定技术关联在一起,不是语言层面的一级特性,远不如Java的接口优雅,可惜可惜!
编译器使用的是基类构造函数unit1中首先遵循的是友元的规则,
因此private中的构造函数可见,而根据你前面所提到的“就近原则”,
既然在类中找到了一个构造函数,自然就不会去找父类的方法。
从这一点来说,unit1中的表现也是合理的。C++中同样有友元的概念,
从对友元的实现来说,我倒认为Delphi比C++更好些
因为C++中是通过关键字来标识友元的,
类和类的友元允许分属不同的文件中,在文件比较多的情况下会很难维护,
而Delphi把友元限定在同一个单元中,维护起来会更方便些至于接口机制,你的认识上更是有偏差,
Delphi的接口机制是自COM而来,这是事实,
自Delphi5以后,Delphi里有interface关键字,而且GUID也不是必须的,
这足以说明接口已经成了Delphi语言的一部分,
仔细研究一下,你会发现Delphi的接口与java没有什么两样
要不解释不了A:=TA.Create('s');编译通过的原因命名空间只解释了“整个”TA类是否可见的问题,
而对于在同一个单元里,可以看到TA类私有方法这个问题,
如果不提友元,单单的一个命名空间很难让人信服unit2中A:=TA.Create;编译通过,说明unit2已经引用了unit1
否则编译不可能通过的
凡是必须要有GUID的接口,或多或少都和COM有关
早期的Delphi 3为支持COM规范所引入的接口,也必须要有GUID,
这时的Delphi接口机制,算不上真正从语言层面提供接口机制,仅仅是作为一种“外挂”
java接口用关键字定义、不需要从特定的根接口继承、不需要GUID,
这种机制算是从语言层面提供的自Delphi 5以后的接口机制做了修改,也采用了java那种从语言层面提供支持的方式
关于这一点李维在《inside vcl》第六章里也说了
“Delphi的接口机制一开始是为了支持COM而加入Object Pascal的...
到了Delphi 5之后接口机制已经成了object pascal的程序语言通用机制,并不只限于使用在COM之中,
特别是Delphi for .net推出之后,...和COM再也没有依存关系了”
请楼上的搞清楚友元的含义在来做解释!另外,楼主的定义本身就有问题,构造器定义为私有的没有任何意义,纯粹是一种语言测试游戏。构造器一般都是虚方法,尤其在类继承链里面的前端更是如此。虚方法的目的是为了多态,即为了封装。最后,我提醒一点,单元引用可以全局引用和局部引用。如果写成A:=Unit1.TA.Create照样可以compiled。关于接口,无须多谈。请楼上的详细看看《COM本质论》。那里面阐述的非常详细。GUID的目的是为了防止命名空间的冲突,这里的命名空间和语言级的命名空间差不多含义。至于delphi因为何故引入接口,李维的书里面说的也未必准确,就我理解,接口除了支持MS COM规范之外,还有一个重要的用途就是实现模式。接口可以更宽泛的支持变化的封装即多态。这点要不虚方法,抽象类等多态支持途径要好很多。从内存分配来说,减少了内存占用量。从调用速度来看,减少了调用耗费时间。
如果你对设计模式熟悉,可以看到GOF的23个设计模式里面大部分都使用了多态和接口来支持模式的构成技术。
这并不能覆盖TObject.Create,
你要写成constructor create;才可以。
Delphi的类构造函数可以有多个,而且可以任意命名,也允许重载。
比用命名空间来解释要更准确事实上,object pascal里友元和单元、命名空间这些是紧密相关的
“2.18.4 友类
在C + +语言中有友类的概念(允许在其他类中访问私有数据和私有函数的类)。在C + +中这是通过关
键字f r i e n d来实现的,严格地说,在Object Pascal中没有类似的关键字,但有类似的功能。凡是在相同
单元声明的对象都认为是友类,都可以访问其他对象的私有成员。”
这是《Delphi 5开发指南》里面的原话对于友元的定义,《C++Primer》里的原话“15.2友元 ...通过把函数或操作符声明为友元,一个类可以授予这个函数或操作符访问其非公有成员的权利”你的原话“在单元文件里面申明一个包含私有构造器的类,然后定义此类的一个对象,然后调用自身类的私有构造器”
——这难道不是友元?实在是搞不懂,明明可以互为补充的两个概念,怎么就成了不共戴天?
你要C++中的private效果,需要用strict private。
FS这段时间还好?我少上论坛了,只是偶尔来问问题才上来。我倒是几次在google的搜索结果上看到FS的大名。
我没QQ,不过我把我的email PS给你了,
AD也还好吧? 我也给你发了私信
所以“友元是类的一种别称”这种说法实在不敢恭维!:)
在C++中除了在类中声明友元类之外,还可以有友元函数,允许在此函数中访问类的私有成员,而此函数是普通函数,不是任何类的成员。
首先友元这个概念描述是类,不是类的实例对象。在同一个单元里面定义的两个独立的类互称为友元。在Unit1中定义类TA,然后定义TA的对象A,这个时候A不能叫做TA的友元。也根本没有这种叫法。所以友元是类这个级别的概念。同时友元是描述类的命名空间的一种概念,所以友元是类的一种别称。请楼上的看清楚想明白在考虑是否可以恭维。这里的别称范围很狭隘,必须是同一个单元中申明的不同类相互称为对方的友元。 此外,我觉得这里没有必要硬把C++扯进来。 关于你说的Strict Private的解释--“The private keyword actually creates a " friendship" relationship between classes in the same unit. The strict private declaration creates a true private field, not viewable by any other class, not even classes in the same unit.”请你自己先看清楚我上面的回复!OK? 楼主在单元Unit1中声明TA,然后在单元Unit1中定义TA的对象A,我实在不明白为什么如此众多的人说和友元有关系?
私有部分的方法对同一单元中的友元类可公开(但属性或字段不公开),但这里申明的是一个自身类的对象,根本没有友元类的存在。也请DelphiGuy看清楚前面的各项回复再来做答。To 大头鸟 “我在Unit1里面如下声明
TA =class(TObject)
private
a:string;
constructor create(s:string);
end;
注意两点,(1)create我声明成private的(2)后面没有用overload指示字,这会让其覆盖TObject那个默认Create 现在在Unit1中写下代码
A:=TA.Create('s'); //OK
A:=TA.Create; //编译不通过
如上的情况我都能理解,问题在下面
”从一开始楼主写的就是TA和A都在Unit1中。这里不存在友元,所以楼上的各位高手非要把这个解释和友元挂到一起实在不合适。
====================================================
楼主的这个问题和友元没有任何的关系,要有关系也是与命名空间有关系。在一个单元文件里面定义的两个独立类互为友元!请看清楚,是定义在同一个单元里面的两个类互相称为友元。友元这个概念是因为存在命名空间这个概念才存在的。没有命名空间就谈不上友元。
====================================================1. 楼主的问题确实与友元有关,根本原因是Delphi的private成员是所处单元的友元(注意是不仅仅是针对其他类,任何函数/过程都可以访问本单元中定义的类的私有成员),而不是命名空间的限制。
2. “友元这个概念是因为存在命名空间这个概念才存在的。没有命名空间就谈不上友元”这种理解是错误的,在同一单元内照样存在友元关系,而且可以用strict private声明来取消。(当然这里说的“友元”是对类似C++友元概念的借用,因为Delphi中并没有定义“友元”这个术语,也没有相应的关键字。)对这两个问题都可以通过简单的代码来验证:
{$APPTYPE CONSOLE}
program test;type
TClass1 = class
private
Data: integer;
constructor Create(const Name: string);
end; TClass2 = class
strict private
constructor Create(const Name: string);
end;var
A: TClass1;
B: TClass2;constructor TClass1.Create(const Name: string);
begin
writeln(Name);
end;constructor TClass2.Create(const Name: string);
begin
writeln(Name);
end;{ main }
begin
A := TClass1.Create('TClass1');
A.Data := 10; // 由于private成员是本单元的友元,这是允许的
writeln(A.Data);
B := TClass2.Create('TClass2'); // 此行编译通不过,显然不是命名空间的原因
end.
2. “友元这个概念是因为存在命名空间这个概念才存在的。没有命名空间就谈不上友元”这种理解是错误的,在同一单元内照样存在友元关系,而且可以用strict private声明来取消。 先说下第一条:我不讨论楼住的问题了,楼住的问题是显而易见的。我说下友元和命名空间。首先我想说明一下命名空间。一个单元是一个命名空间,一个例程也是一个命名空间,同时一个类的可见性标记也可以限制命名空间。很多Delphi书籍都仅仅把命名空间和单元文件对应,很少有提到命名空间的广泛含义。
如果你定义一个例程,不属于任何类,在内部定义一个局部变量,那么这个局部变量的命名空间就仅仅在这个例程的范围内。说白了命名空间就是描述编程对象的可使用性范围。这是其一!
其二,命名空间必须是某个编程对象的命名空间,可以是一个类,一个对象,一个变量,也可以是一个表达式。所以,其二就是命名空间是描述编程对象的一个概念。对于友类概念,也是说明编程对象的可使用性范围的。因此,友类是命名空间的一种特殊约定,也可以说是一种特殊表现。这个看个人怎么理解。文无定法。编程也如此,一个概念从不同的角度理解肯定会看到不同的结果。DelphiGuy所说的Strict Private其实也是命名空间的一种外在约束。一个编程对象最后的可使用范围和编辑期文件的部署,编程对象的定义方式这两个因素有直接关联。其次,第二条:没有命名空间就没有友元概念——如果把命名空间比喻成一个苹果的价格,把编程对象比喻成一个苹果,那么友元就是这个苹果的附加包装。通过附加精美包装提高苹果的价格。没有价格概念,附加包装也就没有任何意义。这个道理很简单。你在单元Unit1中定义类TA和TB,如下.....
TA=Class
private
FieldA:Integer;
end;
TB=Class
private
procedure ShowPrivateFieldOfTA(AField:Integer);
end;
.....
A:=TA.Create;
B:=(TB.Create).ShowPrivateFieldOfTA(A.FieldA); //Compiled;
.....TB的对象B使用TB的私有方法去显示TA的私有域的值。对于这个代码,在TA和TB申明后两个类的命名空间均为Unit1,即两个类的内容可以在Unit1中被其他编程对象所使用,但要受到可见性标识符的约束。但由于TA和TB互为友元,所以对于对方的私有内容也可以访问,完全不受Private的约束。即友元在命名空间的基础上扩展了编程对象(TA的私有域)的使用范围。很明显,友元是对命名空间的一种修饰,更何况语言这东西务必是先有命名空间概念其次再有友元概念。对于楼上所说的Strict Private说白了也是一种限制和约束或者说是约定。没有命名空间概念,友元这些概念也就没有意义,甚至对可见性标识符例如Private这些东西同样如此。最后我说下为什么先有命名空间后有其他约束性的修饰概念。无论面向过程还是面向对象还是现在炒得很火的面向方面。代码要编辑就存在代码的部署,代码的部署务必存在分离,通过什么分离?当然是文件啊,无论文件后缀是什么,这个要依赖于IDE Creator的喜好。代码分离后便于维护,但同样存在一个问题,被分离的存储代码的文件如何知道对方。因此出现了文件的引用。不引用则被分离的代码不可互知。正因为有为代码部署而出现的以文件方式分割代码以及为让文件相互可知而出现的文件引用,才出现了命名空间的概念。语言中很多概念自身是因为非语言的因素才引入的。如果一个项目所有的代码放入同一个文件,先不说好不好维护代码,至少语言中很多概念失去了其自身的意义。DelphiGuy所言的Strict Private中的Strict仅仅是编译器可理解的一个开关而已。见则完全限制可见性,不见则适当放开可见性。
所以,如果一个类允许从外部访问它的私有成员,那么它的这些私有成员就是外部访问者的“友元”。
这些外部访问者,可以是其他类,也可以是普通函数/过程,二者对应友元类和友元函数(不只C++中存在友元函数,Delphi中也有,虽然没有明确定义,但是其使用方式是存在)。
你的理解,“说白了友元就是类”、“友元是类的别称”等等,我认为是错误的,连适用主体都搞错了。
你说的只能理解成“友类”,这与“友元”的概念是有所不同的,可以定义:如果A类的私有成员是B类的“友元”,那么A类是B类的“友类”。
即便“友类”,也不是象你说的那样“在一个单元文件里面定义的两个独立类互为友元”,友类可以是单向的,在一个单元文件里面定义的两个独立类,如果A类有private成员,而B类只有strict private成员,那么只能说A类是B类的“友类”,反向则不成立。又或者两个类根本没有private和strict private成员,那么它们之间也谈不上友类关系了,本来就是对外部访问开放的,当然也就没有“友”和“非友”的区别了。正是你的这种理解偏差,导致一系列错误推论,你认为“友元”必定涉及两个类(或者多个类)之间的关系,而楼主的问题中只有一个类,所以与“友元”无关。
错了,“友元”是类成员(被访问者),不是类本身,而且友元关系不仅对类,对函数/过程也可以存在(Pascal的主程序体就相当于C的main()函数)。对“命名空间”(namespace)的最通常解释是保证标识符(名字)不出现含糊的域(范围),它肯定是存在的,怎么能不存在呢?最简单的情况也可以理解成一个程序只有一个命名空间。
因此你说的“没有命名空间就没有友元概念”是无的放矢、不着边际。可以说没有氧气人就不能活,但不能反向推理出所有的死亡都是缺氧造成的。
而且你对“命名空间”的理解也存在问题,“命名空间”应该是定义域,而不是使用域,后者是不确定的,可以超出前者的范围。
比如一个类的成员,不管是private、strict private、public,它的“命名空间”就是这个类的范围,能否从外部访问都不改变它的“命名空间”。我理解你说的是使用者看到的范围(scope),你uses A,就可以使用A中的常量、变量、函数等等,反之则不能。但是不管能不能,A中的常量、变量、函数的“命名空间”都是A,并没有改变。
这个姑且不论,就按你的理解“命名空间就是描述编程对象的可使用性范围”,这种解释对楼主的问题来说就是离题太远、太空泛,好比你介绍一个人说“他是地球人”,基本上没有意义。
语法规则的应用有一个最接近原则,也就是说最直接起作用的规则优先适用,不是你把更基本的规则搬出来它就更权威、更能说明问题。比如民法(中国目前还只有一部民法通则,相当于暂行民法)比婚姻法更基础,适用范围更大,但是因此说审理婚姻诉讼要优先适用民法,而不是婚姻法,那就只能是荒唐了。回到楼主的问题,从我前面举的例子代码可以看出,能否从外部访问类的私有成员,直接决定于是否存在友元关系,而不是类所处的命名空间。
即便同一命名空间中的两个类,它们之间可以互为友类,也可以是单向友类,也可以不是友类,不管哪种情况,类本身,还有类的成员,其命名空间都没有发生变化,这个你不能否认吧。
而且这个问题与编译原理没有直接的关系,依据同样的编译原理,可以设计出语法规则差异甚大的语言来,你能说哪个的设计没有遵循编译原理?就问你一个问题:
在A单元中使用B单元中的变量V,和在B或者其他单元中使用V相比,V的使用范围发生了变化,但是V的命名空间发生变化了吗?
很明确,它仍然是B.V,没有变成A.V,也没有变成(A+B).V。
如果你不认同这一点,那只能说对命名空间的理解上差别太大,各自保留意见吧。:)
事实上,“友元”这个词在英文中只是friend,只有“友”的意思。
如果
A类对B类开放其私有或者保护的成员,则B类是A类的友元类(friend class),A类是B类的befriended class(由于很难找出一个中文词表达这个概念,所以只好使用“友类”这个词)。
A类对C函数开放其私有或者保护的成员,则C函数是A类的友元函数(friend function)。
我在前面没有写保护的成员,部分原因是由于楼主的问题是在讨论从类外部访问其私有成员,不过说明确实是不严谨的。:)
“在A单元中使用B单元中的变量V,和在B或者其他单元中使用V相比,V的使用范围发生了变化,但是V的命名空间发生变化了吗?
很明确,它仍然是B.V,没有变成A.V,也没有变成(A+B).V。”当你在A中引用B,则V的命名空间自然会扩大。如果你要说不扩大,我也没办法。只能保留各自意见了。
如果你要明白编译原理,我解释一下为什么命名空间会扩大。命名空间说白了就是编译器编译文件的时候记录的文件系统的树结构的结点而已。你上面所谈到的友元只不过是这个结点的一个引用而已。编译过程的语义分析阶段将建立一个申明类型和变量的表结构,此结构的一个字段用来记录命名空间的变化。之所以说是变化,是因为编译是一个过程,其间会关联多个文件。在编译结束后,此表结构的用来记录命名空间的字段内容被确定。但对于动态联遍的DLL以及一些COM应用不存在记录命名空间的字段。对应于Delphi对象模型,此字段对应于代码段中的部分代码。因为代码段中不存在什么表结构。如果你在A单元中定义了变量V,那么当编译器编译V的定义语句的时候会在相应字段中记录V的隶属单元(当然要看V的定义位置,即上下文),并依靠此字段记录内容来对后面要编译的内容进行确定。当编译单元B的时候,发现单元B引用了V,则将V的对应字段进行修改。修改的结果是同时表达A,B两个单元,说白了即文件名称。如果你要认为这个还不叫命名空间扩大,我也没什么可说的了.....整个命名空间的跟踪变化在编译期进行,不在链接期(先编译后链接)。你之前一再提到的友元无非也就是命名空间结点的一个引用而已(不是CPP中的引用,类似于一个类型指针)。至于你所说的Strict,更简单,编译器的一个开关而已。你上面的所有论调,大部分都是在和我强调概念,但实际的编译后台东西我看你并不明白。就像前面有位朋友说的:现实中没有人会定义私有的构造器,因为没有意义。为什么没有意义,因为私有不便多态,无法封装变化。其实编译与语法也是如此。很多语法在前台表现的各有差异,但在编译过程中很多部分都是同等对待。好了,最后你口口声声学过编译原理,懂面向对象,俺留个问题:
重载和覆盖在面向对象语言中的对象模型是什么?在编译过程中又是如何被处理的呢?看清楚,我问的是对象模型是什么?在编译中如何被处理。即编译器看到Overload和Override如何处理对应代码?-----然懂就回答一点,不勉强。看你前面说的也“头头是道”的。这种问题应该很容易回答滴.....
你也就剩下虚张声势的本事了。“当你在A中引用B,则V的命名空间自然会扩大。”这就是你对命名空间的理解???
命名空间(namespace)或者叫名字空间、名称空间,是包含一套标识符的容器,在此内部,标识符可以通过名字来区分。
命名空间是标识符的定义域(也可以包含声明),不是使用域。搞清楚了没?
显然你把标识符的使用范围和它所在的命名空间混为一谈了。好好看看BDS 2006中的解释:
==============================================================
Namespace and Package Overview
A namespace is an element in a model that contains a set of named elements that can be identified by name.
A project consists of one or more namespaces (or packages). A namespace and a package are almost synonyms: the term “namespace” is used for implementation projects, the term “package” is used for design projects.
A namespace (or a package) is like a box where you put diagrams and model elements. Contents of a namespace (package) can be displayed on a special type of the Class diagram.
Each project contains the default namespace (or package) just after its creation.
==============================================================没错,你“这快10年开发看来是白搞了”。
你先是把友元关系理解成只能类对类,对楼主的问题想当然地以为“这里申明的是一个自身类的对象,根本没有友元类的存在”因此不存在友元关系。显然你连友元函数都不知道,类允许外部函数/过程访问它的私有/保护的成员那也是友元关系。楼主的例子能从类外部访问它的私有成员恰恰是友元函数在起作用(在Delphi中,一个类所在的单元中的所有函数/过程都是它的友元函数)。为了自圆其说,接着你又搞出一个标识符的命名空间随着使用它的位置不同而变化的概念,就更加滑稽了。
标识符的命名空间居然随着使用它的位置不同而变化,那还要命名空间有什么用?设计命名空间的目的就是分离程序,消除名称冲突。
“在A中引用B,则V的命名空间自然会扩大”?
扩大到哪里?扩大到A?那岂不是又可能和A中的标识符名字冲突?
你说使用B.V来区分,没错,那恰恰说明V的命名空间仍然是B!
扩大的是使用者的看到的scope,而不是被使用者的命名空间。
A引用B后,直接使用B中的变量V,并非V的命名空间扩大到了A,此V只是B.V的一个别名,V的命名空间仍然是B,并没有被添加到A中。
不只Delphi的单元引用是这样,C++中使用using指示引用其他命名空间也是如此。
你搞不清楚就先好好研究一下,不要东拉西扯,能解决问题吗?
好比你是中国公民,被美国人请去转了一圈,你的国籍就变成美国了?还是双重国籍?
笑话。本来对你还是客气的,点到为止,是你不知好歹,恼羞成怒还开骂了,这除了暴露出你的窘态,能有其他作用吗?:)
你的编译原理问题留着自己玩吧,还是先把友元、命名空间之类的基本概念搞清楚再说,不要走都摇摇晃晃还吹嘘自己百米几秒几秒。
好自为之,你的原话奉还:装B装到头了!
可以说说我是怎么虚张声势吗。我上面讲的编译原理和对象模型哪里有问题可以直接指出来吗!阁下看样子不是对编译原理、对象模型很熟悉吗,那就帮俺FS解释一下我留下的那个问题吧,OK?
不用一会引用这个书一会引用那个书的,自己亲自解释一下不是更有说服力吗.....我从一开始就说明这个问题不是友元的问题,只不过是半路杀出你这个自以为是的人非要在这里争此争彼而已。
不知道阁下学的是什么编译原理,不用装了,装到这份上也不容易了。那问题就是直接提给你的,我就是想看看你到底有多大的本事哦.....“扩大到哪里?扩大到A?那岂不是又可能和A中的标识符名字冲突?
你说使用B.V来区分,没错,那恰恰说明V的命名空间仍然是B!
扩大的是使用者的看到的scope,而不是被使用者的命名空间。
A引用B后,直接使用B中的变量V,并非V的命名空间扩大到了A,此V只是B.V的一个别名,V的命名空间仍然是B,并没有被添加到A中。”——基本纯粹自编!啥叫别名阁下懂吗?“V的命名空间仍然是B,并没有被添加到A中”——学过编译原理吗?我仅是自学,你不是科班吗,呵呵,别装了.....你说错了一点,不是恼羞成怒,老子天生最看不惯的就是不懂装懂的人,球也不定还装的跟个B是的。不好意思骂人了,以前骂习惯了。已经很让你了.....阁下不是有能耐吗,那就劳驾回答一下俺提的那个问题吧?凭阁下的功力回答那个问题应该是很容易的喽.....不用我一提问题就躲得跟个蛋似的.....不好意思,俺没啥文化。静等答复!
这是楼主开的帖,你连楼主的问题都没搞明白,说个一个概念错一个,你还装什么装。就再免费教育你一次:
很明显,你连namespace和namespace member's scope都分不清,还嘴硬。
在namespace中定义或者声明一个identifier,它就成为此namespace中的一个member,它的默认scope就是包含它的namespace,它的潜在scope是所有引用包含它的namespace的区域。
注意此scope是指标识符可见、或者被使用的区域,不是它的命名空间!
这些基本概念,几乎在各种语言的标准中都有,没有什么差别,就随便给你摘一段:
3.3 Declarative regions and scopes [basic.scope]1 Every name is introduced in some portion of program text called a
declarative region, which is the largest part of the program in which
that name is valid, that is, in which that name may be used as an
unqualified name to refer to the same entity. In general, each par-
ticular name is valid only within some possibly discontiguous portion
of program text called its scope.
看清楚没有?一个name的scope是它可以被使用的区域。
另外,在C++标准中明确说明“A using-directive does not add any members to the declarative region in which it appears.”
你这个笑料还搞出什么“当你在A中引用B,则V的命名空间自然会扩大”,真是个大棒槌。
扩大的是使用者看到的scope,或者说被使用者可被用于的scope,不是被使用者的namespace!傻了吧,还嚣张吗?
你还是先把一些计算机语言的基本概念搞清楚再出来卖弄也不迟,就你这浆糊脑子,够你再学个十年的。
你看看你在这个帖子里的表现,不知道自己吃几碗干饭,NB哄哄,鼻孔朝天,进来就咋咋呼呼,打击这个,打击那个。别说你那二把刀水平,你就真是高手,至于这么嚣张吗?
看在这是一个技术帖,而且快过年的份上,一直给你留着面子,容忍你的无礼。
可你倒好,给脸不要脸,连续说错基本概念,不但不道歉,还现出一个泼皮牛二的嘴脸,东拉西扯,胡搅蛮缠,不但无知,更加无耻。
你现在的的表现就象考试不及格被家长暴打的顽童,鬼哭狼嚎还嘴硬:“我出个题你能考及格吗!你先回答我的问题,否则你就不及格...”
哈哈哈...
真TMD丢人。正是:
面壁十年图破壁,
破壁空留南郭名;
大师不甘贻笑众,
再练廿载亦蒙羞。
=============================================================
评论:您知道友元函数吗?
解释:友元关系不仅仅是类对类,类对函数也可以,一个类允许外部函数访问它的私有、保护的成员,就是它的友元函数。
在Delphi中,一个类所在单元的所有函数/过程都是它的友元函数(Pascal的主程序体也是一个过程,相当于C的main())。61楼:当你在A中引用B,则V的命名空间自然会扩大。
=============================================================
评论:您搞得清标识符的命名空间和标识符的作用域的区别吗?
解释:简单地说,命名空间是包含若干标识符的容器,在此空间之内,每个标识符具有唯一的名字。设计命名空间的主要目的就是避免名字冲突。当在命名空间中定义/声明一个标识符后,它就成为此命名空间的成员,这种关系是明确的,不会随着它被使用的区域不同而改变。
而标识符的作用域,就是它可被看到,或者被使用的区域。标识符的作用域包含它的命名空间,但不限于此,是不确定的,随着它被使用的区域而变化。当在A单元中使用B单元的变量V,则V的作用域扩大到A,但是它的命名空间仍然是B(很明确,它是B.V,没有变成A.V)。
举个类似的例子:命名空间就相当于国籍,一个中国公民不论去世界上任何地方,他的国籍仍然是中国,而他出现的位置则可以发生变化(作用域)。
看到了吧,还真是“基础忒次”,还真是“不懂装懂”,怎么就这么有自知之明呢!
就是这么个基本概念都一脑子浆糊的二五眼,还猖狂得不得了,在这个帖子里一出现就上蹿下跳,看人都鼻孔朝天,七个不服、八个不忿,打击这个、打击那个,你说说别人招你惹你了?
“大师”,你那点水平,从你在28楼的发言就看得一清二楚了。我一直对你引而不发,容忍你的无礼,给你留着面子,让你有个全身而退的机会。(不承认?那就好好看看在你60楼彻底撒泼之前,我说过过分的话没有?)
一是因为这是一个技术帖,不想引发不相关的争论。
二是因为快过年了,不想伤你,把你搞得灰头土脸的没什么意思。
是你不知死活,一直咬我,我不得不对你痛下杀手。
现在你爽了吗?吸取教训吧。:)
你可以选择在这个帖子里充当的角色,谦虚的旁观者,积极的参与者,或者一个泼皮无赖。
你已经作出了选择,就要为你的选择付出代价。
你可以决定如何开始,但是如何结束,那可由不得你了。:)
”——偶不知道如何形容你了,整个一个没娘的娃娃!是不是以为俺躲着你呢?太自负了吧.....快回去好好翻翻书来回答我那两个问题吧,不用每天闷着心思在这里搅尽脑汁地来损人了,想骂就骂吧,偶FS不会介意的,但要骂就骂的像个男人点,别跟个青楼的娘们是的扭扭捏捏,又作诗又祝你哥我新年快乐什么的,整个一娘们德行。最后和你说一句,快回答我的问题吧,回答出来俺FS自动退出,认可你的皮毛理论,不回答我们就一直骂下去。忘了告诉你了,前两天收拾家没时间上来.....不要以为你爷爷躲着你个小B孩.....鼠年到了,俺不祝你快乐了,只因为不想像你跟个娘们一样在这里装B.....过了大年,FS爷爷陪你继续在这里演戏.....OK?煞笔大白痴.....呵呵.....
就这么一张被大家的目光烤成死狗的贱脸,还要嘴硬。
本来看你这被修理得狼狈不堪的可怜样,还想放你一马,可你倒好,给脸不要脸,还趁着我不在的这几天放个屁、吹个牛,小小的自慰一翻,以为可以找回你那一钱不值的面子。真是个TMD笑料!那也只好把你一棒子打死,让你彻底没脸见人。你要是搞不懂命名空间(namespace)和作用域(scope)的概念,就花点时间好好研究一下,而不是一再跳出来胡说八道、丢人现眼!
技术问题,是你死缠烂打,装傻充楞就可以任意篡改、混淆视听的吗?
就你这种基本概念都搞不明白的浆糊脑袋,你还以为喷“编译原理”四个字就可以在我面前耍宝?你不是个笑料还能是什么?看来不用编译原理狠扇你几个大嘴巴你就皮子痒痒!
你随便找译本《编译原理》,看看其中的符号表部分写的是什么?
比如经典的《编译原理及实践》第六章 6.3.3 作用域规则和块结构 讲的是什么???
是“作用域”还是“命名空间”?!
大嘴巴狠抽你这个给脸不要脸的贱货!看你再嘴硬。
你这个囔糠的夯货!犯贱的呆子!你一再被我牵着在大家面前溜,还不长点眼色,你是不是根本就不知道这世界上还有羞耻两个字?我就再最后教你一次,什么是作用域,什么是命名空间。
随便摘一点msdn上的资料:
http://msdn2.microsoft.com/en-us/library/b7kfh662.aspx
Visual C++ Language Reference
Scope
C++ names can be used only in certain regions of a program. This area is called the "scope" of the name. http://msdn2.microsoft.com/en-us/library/5cb46ksf(VS.80).aspx
Visual C++ Language Reference
Namespaces (C++)
A namespace is a declarative region that attaches an additional identifier to any names declared inside it. 睁大你的狗眼看好了!两者是一回事吗?FrameSniper,你为什么落到被反复羞辱,欲罢不能的地步?你觉得委屈,觉得不甘心就好好反省一下你在这个帖子里的表现,是你的嚣张+无知+无耻的丑恶嘴脸让你自我毁灭,不是别人和你过不去,这是你自找的!
TA =class(TObject)
private
a:string;
constructor create(s:string);
end;
注意两点,(1)create我声明成private的(2)后面没有用overload指示字,这会让其覆盖TObject那个默认Create 现在在Unit1中写下代码
A:=TA.Create('s'); //OK
A:=TA.Create; //编译不通过
如上的情况我都能理解,问题在下面 在Unit2中写下如下代码
A:=TA.Create; //编译通过,OK
为什么会出现这种情况?
-----------------------------------------------------------------------------------------
搂主 A:=TA.Create('s'); //OK
A:=TA.Create; //编译不通过 真能通过吗?
var
a: string;a := ta.create(''); 能通过?
你这种笑料,又“不谈命名空间和作用域”了?
哈 哈 哈 哈 哈 ...
那你前面一直在放屁呀?
落慌而逃还要摆个POSE,你就丢人吧你。
回答你的问题?你还是先把基本概念搞清楚,先把楼主的问题搞清楚!
你这种转移话题的遮丑伎俩,有用吗???
你你这种一脑子浆糊、一肚子稻草的废柴,还有脸出来喷什么“十年研发”?!你这十年是吃屎长大的呀?
你已经倒了,还做梦挽回你那早就被剥了皮的“面子”呀,省省吧。正是:也曾上山寻虎,
亦想下海擒龙;
搬梯扶摇觅月宫,
咕咚。欲学慧能讲法,
更慕达摩传经;
奈何周公早收工,
轰隆!
再顺便教育你一下:你那白痴问题在C++标准化文档中解释得很清楚,也就你这种废柴以为可以搬出来忽悠一下。
建议你这种知道自己“基础忒次”、“不懂装懂”的,最好找一下C++STANDARD-ISOIEC14882-1998看一看,不要再连作用域和命名空间都分不清了!
你看你这丢人现眼的德性,以嚣张+虚张声势开始,以被修理得体无完肤+丑态百出而落慌而逃。
你落慌而逃还要摆个POSE,还整出一个“孰对孰错懂的人一看就明白,可惜CSDN这地方大部分都是初学者,所以类似你这种B货可以随便侃而不露马脚”,还真是有自知之明啊,你有这自知之明早干什么去了?非要吃了苦头才知道后悔吗?!
可惜你这自知之明还是差了一点:你没能“不露马脚”,你才两个帖就被扒得光溜溜,成了彻头彻尾的笑料。你不是还要阿Q吗?对不起,连这点面子我也不给你,非把你玩得死翘翘不可。
这么说吧:
咱们两个,谁不懂装懂,连基本概念都没搞清楚就出来虚张声势,打击这个,打击那个,谁就TMD不是人养的,全家遭雷劈!
怎么样?我看你再嘴硬???
哈 哈 哈 哈 哈 ...
给脸不要脸的东西,你趁早买块豆腐一头撞死算了。
既然你这么爱犯傻,那就请大家再好好欣赏一下你的“精彩表演”:19楼:CSDN这烂地方,我再不回答问题就更烂了.
22楼:这里和友元没有任何关系,仅和命名空间有关系!
28楼:友元这个概念是因为存在命名空间这个概念才存在的。没有命名空间就谈不上友元。
29楼:各位的基础我感觉也有点忒次了。友元是类的一种别称。
43楼:从一开始楼主写的就是TA和A都在Unit1中。这里不存在友元,所以楼上的各位高手非要把这个解释和友元挂到一起实在不合适。
61楼:当你在A中引用B,则V的命名空间自然会扩大。
64楼:学过编译原理吗?
68楼:编译的东西和对象模型的东西我自认很清楚,
74楼:楼上的,我请你去认真看看编译原理在来这里做解答。误了自己不要紧,本身就是个死要面子的东西,不用跑到这里来误人子弟了,OK?
76楼:不用和偶在这里谈什么命名空间这些东西了。我说了,有点本事就回答下我的问题。不用和我撤东撤西的什么作用域和命名空间了.....别J8和老子废话了,不用拿什么编译原理的书来压我。大家看到了吧,这么个笑料东西,还嚣张得不得了。可惜一上来就闹了个大笑话,连友元关系都没搞明白,友元函数都不知道,就整出一个“这里和友元没有任何关系”,摔了个嘴啃泥。
等我告诉他类和函数也可以构成友元关系(友元函数)之后,为了遮丑,他又死咬住“命名空间”不放,开始喷“友元这个概念是因为存在命名空间这个概念才存在的。没有命名空间就谈不上友元。”
然后我又告诉他,命名空间(namespace)和作用域(scope)不是一个概念,标识符的作用域会随着它的使用区域不同而变化,但是标识符的命名空间不会随之改变。他继续嘴硬,还虚张声势,扯出“编译原理”来了。
然后我又告诉他,《编译原理》上讲的是作用域,不是命名空间。他就只剩下摆POSE了,作用域、命名空间、编译原理都不谈了。哇哈哈哈哈... 虚张声势->狼狈不堪->生搬硬套->恼羞成怒->丑态百出->落慌而逃,就是这位FrameSniper(本名范傻)的生动写照。
我不想标榜自己的人品如何如何好,但是至少一个原则还坚持得很好:尽量与人为善,不主动攻击别人。但是如果有人先攻击我,尤其是象范傻FrameSniper这种无知还嚣张得不知道自己吃几碗干饭的货色,那对不起,我就非把他狠狠修理,彻底踩死不可。象范傻FrameSniper这种货色实在令人费解,搞不懂他到底嚣张个什么劲?吹嘘什么“十年研发”,居然连友元函数都不知道,连标识符的作用域和命名空间都分不清,吹嘘“编译的东西自认很清楚”,可是连《编译原理》上写的是作用域还是命名空间都弄不明白。这种说一个概念错一个概念的钝胎,还嚣张得上蹿下跳、摇头摆尾,打击这个、打击那个,这种败类,我不修理他,对得起天理吗?对得起在这个帖子里被他无端攻击的人吗?:)
讽刺偶有什么用?能满足你的脆弱的心理吗?呵呵.....
前面还像个人,突然被我一句骂激的想个疯狗一样,本质乎?正常的人是不会有你这种反差的.....
等着你回答问题。
不过提一点 FrameSniper骂人在先不对 DelphiGuy紧追不舍也不对(你谈的概念过于表面化 内部机理看来不是很明白清楚)-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
本人现在研究方向为编译原理 目前就读华东理工大学研究生二年纪
不敢说对编译原理很熟悉 但“研究”了这两年多 多少懂一点 嘿嘿
两位不用继续争论 FrameSniper应该学会用简单的语言阐述理论
DelphiGuy应该透过表面看本质
看看这位的“简历”,真够简的:
http://hi.csdn.net/compilerdev
所在行业:未填写
社区头衔:
个人简介马上查看他的简历
未填写
个人专长
未填写
专家分: 目前总共有0分 马上查看他的帖子博客:目前总共有0条评论 马上阅读他的博客
访问量:0 排名: 20000名之外 文章数:0条
资源:目前总共有0分 马上查看他的资源
上载资源数量:0 下载资源数量:0
空间统计
共有0人访问过此空间,排名574681 位
发表文章:0篇, 发表帖子:2个; 资源:0个注意这“发表帖子:2个”是CSDN统计的一个BUG,点击右边的“发表帖子:2篇”查看,就只有这一篇回复(到目前2008-02-20 20:52为止)。
分明就是个刚注册就直扑过来的托。哈哈哈哈哈...
范傻,你呀,都可悲到这种程度了!让人说你什么是好啊。你再狡辩也没用,你连友元函数都不知道,上来就整出个“楼主的例子中没有友元关系”,那能叫“基本正确”???再“透过现象看本质”,命名空间和作用域也不是同样的概念,标识符的明明空间也不会随着它的使用区域不同而变化。至于两者的区别,我在前面的帖子里已经讲过多次了。范傻,你就省省吧。你也就剩下阿Q那点本事了,你以为虚张声势+托就有用啊???能挽回你那早就被扇烂的脸哪???完全脱离现实的幻想!你不但可悲,精神都不正常了。
对你有一言相劝:有病治病!不要丢人误己!
你早就倒了!还做梦想翻身哪?还玩这么拙劣的马甲手段(好好好,不是你的马甲,是贱脸找抽的马甲、是生孩子没P眼的马甲、是全家遭雷劈的马甲... 哈哈哈哈哈,你满意了吗)?你的精神状态显然已经很不正常了。
就你这种说一个概念错一个概念的笑料嘴脸,你的那点脸早在28楼就丢没了,还不知死活、没脸没皮,一再跳出来装模作样、虚张声势,你还有没有点羞耻心和自我认知能力呀?你一次次被我牵出来溜给大家看觉得很爽吗?!
从生物学来看,你的特征就是神经系统发育不全,额叶呈原始形态。在心理学上,你就是典型的认知型人格障碍,对自我和外部世界的认识完全脱离现实,有明显的妄想症状。什么是“太自以为是”、“过于肤浅”、很多深入一些的东西不是很清楚”呢?
只要把如下几个和楼主的问题相关的问题回答一下就很清楚了:
1. 楼主的例子里到底有没有友元关系?
2. 作用域和命名空间是一回事吗?
3. 《编译原理》中符号表部分讲的是作用域还是命名空间?我要看看你这个整出“楼主的例子中没有友元关系”、“友元是类的一种别称”、“命名空间就是描述编程对象的可使用性范围”、“当你在A中引用B,则V的命名空间自然会扩大”...诸如此类笑料的人是如何“不自以为是”、“不肤浅”、很多深入一些的东西很清楚”的???
就你这种嚣张+无知+无耻的德性,天都亮了N次了,你还做梦哪?技术上的正确与否,那是有客观标准的,是你胡说八道、胡搅蛮缠就能篡改的吗?别说你整一个马甲(还如此拙劣),你就是整1000个马甲上来发帖,你的无知还是无知,你出了丑还是出了丑,能改变吗?!
早在2006年,CSDN上就有人这么评价你“FS只是个没文化没素质的盲流而已”,此评价只能说:精辟!
DelphiGuy确实有才,这个不得不佩服,技术上你和FS到底谁对谁错我也没能力判别,不过你不是说这是技术贴,也不想骂人吗?你讽刺了将近有10个帖子了,还顺带把一个新人给讽刺了,虽然你骂人从来不带脏字吧,但是如果那个新人真的不是马甲呢?你这么一来不是也把CSDN的牌子砸了吗?不是也把自己的牌子给砸了吗?就好比说你被疯狗咬了一口,结果你反过头来把那狗一口咬到死,这不是比疯狗还疯狗了吗?
保持点风度吧,你已经神经过敏了,好像所有出来劝架的或者说FS一句好话的人就都是他的马甲,都是要给FS翻身似的,殊不知你在发挥你的口才展示你的精明的时候,已经把你的风度丢的一干二净,慢慢沦为你自己骂的那一类人了。
专家分: 目前总共有137分
Delphi:109分 扩充话题:13分 MS-SQL Server:10分 我想就算是马甲,也不容易在短时间攒这个分数吧?另外,你可以看看我的空间,
共发表文章:0篇,发表帖子:84篇;资源:0个;网摘:0个
这些帖子是从07年6月到现在发的,FS的预见性是不是太强了一点啊?PS:DelphiGuy,我不是想跟你争什么,说实话,我还是满佩服你的,因为你讨论的这些问题我都是不怎么懂的,而且你就算骂人也从来不带脏字,这不是一般人能做到的。但是我看不惯的就是你到现在还咬着人不放,慢慢的还发展到见谁咬谁,这实在是让我这个本来欣赏你的人很失望。希望你悬崖勒马,就算以前别人是疯狗,我也不希望你打了疯狗之后自己又成了疯狗。况且别人也不一定是疯狗,只不过你们意见不合而已,不至于一棍子把人打死啊。
这位,你是不是托我并不关心,也不做判断。但是那位肯定是马甲,你也不至于看不出来吧。我修理这个范傻,不是因为他说错了技术上的东西,他错了与我有什么关系?完全无关紧要的。根本原因是他的嚣张+无知+无耻的态度,凡是把这个帖子从头到尾看一遍的人都会承认,他落到这种下场纯粹是他自找的。
只要他还还敢跳出来嚎叫,打狗行动就要继续进行。在这CSDN上被我踢死的,范傻不过是平淡无奇的“之一”,他不是第一个,也不会是最后一个,无知还嚣张得上蹿下跳、出言不逊的人多得是,就象苍蝇,打也打不完。:)
你的面子早就没了!你也早就成了一条被打断脊梁的赖皮狗!还不知死活,你到底知不知道世界上还有羞耻二字呀?要回答问题?你还是先回答一下和楼主相关的问题:
1. 楼主的例子里到底有没有友元关系?
2. 作用域和命名空间是一回事吗?
3. 《编译原理》中符号表部分讲的是作用域还是命名空间?你不是彻底不要脸了吗?好!你出来嚎一次,我就在这剥一次你的皮!看看你造出的
“楼主的例子中没有友元关系”、“友元是类的一种别称”、“命名空间就是描述编程对象的可使用性范围”、“当你在A中引用B,则V的命名空间自然会扩大”...诸如此类的笑料。就你这种货色,你这“十年研发”还真是白搞了,你趁早把自己捏巴捏巴钻马桶里算了(记得冲水)。就你这种一脑子浆糊、一肚子稻草的东西,还在我面前卖弄你的猴屁股、吹什么“编译原理”?整个一个笑料!
你还喷什么你的问题?能救得了你的命吗?早在前面的帖子里就教育过你:
你那白痴问题在C++标准化文档中解释得很清楚,也就你这种废柴以为可以搬出来忽悠一下。
建议你这种知道自己“基础忒次”、“不懂装懂”的,最好找一下C++STANDARD-ISOIEC14882-1998看一看,不要再连作用域和命名空间都分不清了!
你要看不懂的话就再教教你,在
3.4 Name lookup
10.3 Virtual functions
13.3 Overload resolution
部分有详细的解释,还需要给你抄出来吗?白痴!你以为我不理你的茬就是不会?你不就是想转移话题遮丑吗?还玩这种顽童伎俩?做梦!
你看看你这种丢人现眼、垂死挣扎、丑态百出的表现,还真是活脱脱一个考试零蛋被家长暴打屁股的顽童,被打得鬼哭狼嚎还嘴硬:“我出个题你会吗?你答不上就不及格!我就100分...”。
呵呵呵... 真是没有最傻,只有更傻,FrameSniper再创犯傻新记录!我看你还能挣扎到几时!