Problème d' #import

damien_t

Membre actif
21 Juin 2004
295
13
43
Je voulais faire rapidement un petit programme et j'ai eu pleins de problèmes toute la journée. J'ai essayé d'isoler le bug et j'en suis arrivé au programme minimal suivant:

DataStore.h:
Bloc de code:
#import <Cocoa/Cocoa.h>
#import "ApplicationController.h"

@interface DataStore : NSObject {
    ApplicationController *applicationController
}
@end
ApplicationController.h
Bloc de code:
#import <Cocoa/Cocoa.h>
#import "DataStore.h"

@interface ApplicationController : NSObject {
    DataStore *dataStore;
}

@end
ApplicationController.m:
Bloc de code:
#import "ApplicationController.h"

@implementation ApplicationController
@end
DataStore.m:
Bloc de code:
#import "DataStore.h"

@implementation DataStore
@end
Ce programme ne compile pas et me donne une "Error: parse error before 'DataStore'" (dans le fichier ApplicationController.h)
Ce programme compile si j'enlève la ligne "#import "ApplicationController.h"" et la ligne "ApplicationController *applicationController" de DataStore.h mais bien évidemment j'en ai besoin pour accéder aux méthodes de l'ApplicationController et vice versa pour DataStore qui a besoin d'accèder à ApplicationController.
Si j'ai bien compris le role de de la directive #import, elle inclue le fichier qu'une et une seule fois. Ce qui ferait que ApplicationController.h s'incluerait lui-même. C'est certainement le problème mais j'ai aucune idée sur la manière de le contourner.

J'ai du louper quelque chose d'hyper simple, mais j'ai tout vérifier et là je sèche. Ce qui m'étonne d'autant plus que j'ai fait des programmes beaucoup plus compliqués et que je ne suis jamais tombé sur ce genre de problèmes.

Bref, si quelqu'un pouvait me dire le truc évident à coté duquel je suis passé.

Merci d'avance.
 
Tu es tomb&#233; dans un probl&#232;me de "r&#233;f&#233;rences crois&#233;es".
Pour en sortir, il suffit de d&#233;clarer les classes utilis&#233;es dans tes .h :
dans DataStore.h, tu ajoute "@class ApplicationController;" et dans ApplicationController.h, tu ajoutes "@class DataStore;" avant la directive @implementation. Ceci informe le compilateur que tu utilises des objets de ce type.
Et tu n'ajoutes les includes que dans les .m, comme cela le linker y retrouveras ses petits.
 
Super merci, ca marche !

Par contre, je n'ai pas compris quand est-ce qu'il vaut mieux utiliser @class MaClasse ou #import "MaClasse.h". Dans mon cas particulier, je sens bien que c'&#233;tait pas un #import qui fallait utiliser. Mais dans le cas g&#233;n&#233;ral, si c'est juste pour d&#233;clarer l'utilisation d'une classe dans le header d'une autre classe, je suppose que dans la plupart des cas, un simple @class suffit, non ?

Edit: Apr&#232;s v&#233;rification, c'est exactement la bonne solution. Au moins, j'aurais appris un truc aujourd'hui :

Typically, an interface file uses @class to declare classes, and the corresponding implementation file imports their interfaces (since it will need to create instances of those classes or send them messages).

The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly.