2012-02-11 68 views
1

我正在創建一個小程序,它包含我從桌面上運行的幾個源文件(我不使用Xcode),它是從命令行編譯的。由於一切都非常小,我想跳過使用頭文件,並在我的.m文件中的一切。它想是這樣的:Objective-C中不使用頭文件

Foo.m 

#import <Foundation/Foundation.h> 

@interface FooClass : NSObject { 
} 
- (void) fooFunction; 

@end 


@implementation FooClass 

- (void) fooFunction { 

    NSLog(@"Printing bar"); 

} 

@end 




Main.m 

#include <stdlib.h> 
#import "FooFunction.m" 


int main (int argc, const char *argv[]) 
{ 

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSLog (@"Running...."); 

    FooFunction *foo = [[FooFunction alloc] init]; 
    [foo fooFunction]; 

    [pool drain]; 
    return 0; 

} 

當我嘗試編譯此我得到ld duplicate symbol fooFunction blahblahblah for architecture x86_64

的任何想法,我做錯了什麼?

回答

4

包含.m文件(或.c/.cpp)等實現文件是一個壞主意。如果你需要包含一個文件,它可能應該是.h。

通過包含Foo.m,您有兩個實現FooClass現有,鏈接器不喜歡。這是因爲包含文件就像是該文件的複製和粘貼。

在您的示例中,編譯器編譯兩個文件 - main.m和Foo.m,並且在@implementation部分中有FooClass

你應該在所有編譯的文件之間有一個實現,但是你可以多次聲明接口,這就是我們把接口聲明放在頭文件中的原因。通過這種邏輯,雖然它不是慣例,但從技術上講,你可以把所有東西放在一個main.m文件中,然後編譯它。然而,爲了理智,一旦你有更多的代碼,你應該把它分解成class.h/.m文件。

還有一個不使用頭文件的選項,只添加@interface部分到文件中,但是我不推薦這麼做,因爲你會通過鏈接器地獄當你編輯這些副本中的一個並忘記另一個時。在你的情況下,你只需將FooClass@interface部分添加到main.m文件的頂部。

+0

那麼解決方案是將接口代碼放在Main.m文件中?我很感謝你的解釋,但我仍然不清楚如何避免使用頭文件。 – 2012-02-11 09:58:12

+0

你可以這樣做 - 我更新了我的答案來討論這個問題。 – 2012-02-11 10:01:37

+1

@Eric:避免頭文件意味着只有一個名爲main.m的文件。但是,如果您不包含任何頭文件,那麼您將無法使用任何庫/ API或組織代碼。如果你有多個源文件,你應該使用頭文件。如果你有一個main.m,那就完全沒有必要。 – 2012-02-11 10:08:50