作者godfat (godfat 真常)
看板java
标题Re: [问题] 问一个新手问题
时间Thu Mar 27 18:37:06 2008
很久没写点什麽了(或是说都没贴过来),就在 java 板讲点 c++ 的废话吧... @_@b
当然也只是一些个人的理解就是了...
※ 引述《PsMonkey (痞子军团团长)》之铭言:
: 而 c++ 似乎没有这样分,反正 method 有在 class 宣告就好
: 有没有在 class 里头 define 没关系,也许某个档案的某个角落就有实做
: 你必须自己去寻找、分辨
: 我是不知道 c++ 这样作有什麽好处,
: 也许高手可以用这个模糊地带玩出一些方便开发的优点
: 我是懒惰的逊咖,害怕这种事情...
其实这样做的原因很多,并不单单只是因为「好」或是「习惯」。
就像我在前几篇的推文提到的,这样作比较大的原因是来自 compilation model.
由於 c/c++ 远比 java 静态,他在编译的时候就需要各个 class/function 的
原始资料,也就是 source code. 然而我们需要的其实只有 declaration,
并不需要 definition. 所以很自然地就把 declaration 放在 header,
并让其他 source code 去 include 进来。也就是说,每个 compilation unit
都会需要所有用到的 class/function 的 declaration.
(不过其实 class header 就已经是 class definition 了,但这边先不分这麽细)
於是当我们提供自己的 library 时,可以提供 binary + header 即可,
对方可以完全不用看到实作细节到底是怎麽样。这样一来可以隐藏实作细节,
二来有人不想 open source 却要作 library, 就能用这种方式。
然而 java 这部份的资料完全是动态载入的,所以就不需要 header,
更不会有恐怖的 circular dependency? 其实我不确定,java 不常写 @_@
不过刚刚试了一下,确实可以搞出有趣的东西...
a.java:
class A{
B b;
}
b.java:
class B{
A a;
int d;
}
这样一开始是没办法编译的,但是可以先把 class A 的 B b; 拿掉,
随便做出个错误的 A.class, 接着 compile b.java, 再把 a.java 加回 B b; 并编译。
另外写了个 c.java:
class C{
public static void main(String[] argv){
A a = new A();
B b = new B();
a.b = b; b.a = a;
a.b.a.b.d = 10;
System.out.println(b.a.b.a.b.d);
}
}
这样刚刚测试是可以跑出 10 的...
小实验中没问题,大程式这样会不会挂我就不知道了...?
有请熟悉 java compilation model 的 @_@b
而在 c/c++ 中理所当然不能搞这种事,因为 header 就等於是 spec,
如果让两个 binary 中得到的资讯不同,我想程式在 runtime crash 掉的可能性很高
於是有了 forward declaration 与 declaration 和 definition 分离这两件事,
使得可以写成这样:
a.h:
#ifndef _A_H_
#define _A_H_
class B; // 宣告,没有定义
class A{
public:
B* b;
void f(); // 宣告,没有定义。因为如果在这定义,不能使用还没定义的 B!
};
#endif
b.h:
#ifndef _B_H_
#define _B_H_
class A;
class B{
public:
A* a;
int d;
};
#endif
而这同时也是因为 #include 只是作 text 上的处理,不是什麽模组化的东西。
当然不可能在 a.h 去 include b.h 然後 b.h 又去 include a.h...
所以至少 A 或 B 其中一个一定会看不到对方真正的「定义」。
但是如果「宣告」和「定义」分离了,那麽就能让 A 和 B 互相使用对方的东西...
这跟 OO 无关,也不是说宣告和定义分离会特别好用,只是 c/c++ 的
compilation model 需要这种分离才能做到某些事情。如果没有碰到上面那种事情,
要全部的东西都写在 header 也不是不行,小心 multiple definition 就好了。
也就是说 c++ 其实没什麽良好的模组化能力。有人在 c++0x, 也就是下一版的 c++
中提出相关的 proposal, 我没记错的话是没有通过的。原因我想很简单,
这影响层面太大了.... 而 09 年又只是明年 XD
另一方面,如果你「信任」对方的话,只看宣告和文件也会比看到一堆定义来得清楚。
虽然说其实现在编辑器这麽强大,要把所有定义 fold 起来,让 *.java 看起来像
*.h 那样只有宣告的「样子」,也不是什麽大问题...
btw, 如果再谈到 c++ template, 那情况就会变得很恐怖了。恐怖在於原本的宣告和
定义分离,某种程度上会无法作用。这时候就要靠只有 comeau 实作的 export 了...
然後其他 c++ compiler 全部都会无法编译... 除非要手动去 instantiate...
越静态的东西,编译起来就越麻烦...
--
生死去来、棚头傀儡、一线断时、落落磊磊
《花镜》-世阿弥
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.135.28.18
1F:推 Fightsea:又多学到了一些东西! 03/28 12:49
2F:推 wctang:这篇写得好,早看到我就不用多嘴了 :) 03/28 18:28
3F:推 wctang:现实上要共用的东西都不该弄成C++的形式,问题太多了 03/28 18:34
4F:→ wctang:除非是 open source 的型式... 03/28 18:37