2012-02-11 69 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