包含文件时出错

时间:2012-01-05 13:57:53

标签: objective-c cocoa oop class import

我有一个班级结构

Class A
{
   Object of classB
   Object of classC
}

现在为此我有文件A.h / A.m B.h / B.m,C.h / C.m. 现在我有一个单独的文件G.h,它有许多全局变量,所有的变量都由A,B,C类使用 现在我在A.h里面导入了B.h,C.h,G.h。我还在B.h和C.h

中单独导入了文件G.h.

现在,在构建项目时,我在全局变量上收到重复符号的链接错误(这可能是由于多次包含文件G.h)。

我该如何解决这个问题?以下是我的代码结构

//A.h

#import "B.h"
#import "C.h"
#import "G.h"

@interface A : NSObject {
  B *b;
  C *c;
}
//B.h
#import "G.h"

//C.h

#import "G.h"

//G.h
A *a=nil;
@interface G : NSObject { //whole class is empty}

2 个答案:

答案 0 :(得分:3)

你应该在G.h声明你的全局变量,但在G.m定义它们,以便它们只在目标中链接一次。因此,例如,如果你有一个全局定义的字符串常量,你可以这样做:

<强> G.h

extern NSString const *appName;

<强> G.m

NSString const *appName = @"My Great App";

在粘贴的代码中,它是被复制的A实例。它被导入到彼此的翻译单元中,但每次都使用相同的名称,这意味着编译的对象无法链接。假设您想要一个名为A的共享a实例,您可以执行以下操作:

<强> G.h

@class A;
extern A *a;

<强> G.m

#import "A.h"
#import "G.h"

A *a = nil;

答案 1 :(得分:0)

在类标题中使用@class编译器指令,而不是导入其他类的标头。 @class提供给定类的前向声明,因此您可以推迟导入其标头,直到您真正需要它为止,这通常位于相应的.m文件中。

所以不要这样:

 #import "B.h"

 @interface A : NSObject
 {
     B someObj;
 } 

......做这个

 @class B;

 @interface A : NSObject
 {
     B someObj;
 } 

现在编译器将理解B是类的名称,因此允许您将其用作数据类型而不导入B的标头。