Re: [問題] 問一個新手問題
很久沒寫點什麼了(或是說都沒貼過來),就在 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
推
03/28 12:49, , 1F
03/28 12:49, 1F
推
03/28 18:28, , 2F
03/28 18:28, 2F
推
03/28 18:34, , 3F
03/28 18:34, 3F
→
03/28 18:37, , 4F
03/28 18:37, 4F
討論串 (同標題文章)
本文引述了以下文章的的內容:
問題
1
1
完整討論串 (本文為第 12 之 14 篇):
問題
4
5
問題
2
2
問題
3
4
問題
2
2
問題
1
1
問題
1
2
問題
4
5
問題
1
1
問題
1
2