#import 不能防止循环调用?

发布于 2024-12-07 10:20:06 字数 829 浏览 0 评论 0原文

我有两个类 ClassA 和 Class B(它们是 viewController)。
A 类是 B 类的委托。
ClassA“laucnhes”和 ClassB 的实例。
ClassB 调用 classA 上的方法。

假设是这样:

#import "ClassB.h"

@interface ClassA : NSObject {
    ClassB* subController;
}

- (void) doThis;

-------------------------------

#import "ClassA.h"

@interface ClassB : NSObject {
    ClassA* delegate;
}

-------------------------------

@implementation ClassB

- (void) someMethod {
   AnObject* myObj = [self.delegate.arr objectAtIndex:8];
   [self.delegate doThis];
}

这样做,A 必须导入 B,B 必须导入 A。

如果 B 不导入 A(仅使用 @class A),则 A 中使用的属性会出现编译错误。
如果 B 导入 A,则 ClassA* delegate 行上会出现编译错误。

为什么我会出现这些编译错误? #import 不会再次保护递归调用吗?

我不需要解决方案来解决该问题,我知道如何做到这一点。
但我想知道为什么我的 #import 会导致这些问题。这些不是#includes...

I have two classes ClassA and Class B (they are viewControllers).
Class A is a delegate of classB.
ClassA "laucnhes" and instance of ClassB.
ClassB call methods on classA.

Let's say it's :

#import "ClassB.h"

@interface ClassA : NSObject {
    ClassB* subController;
}

- (void) doThis;

-------------------------------

#import "ClassA.h"

@interface ClassB : NSObject {
    ClassA* delegate;
}

-------------------------------

@implementation ClassB

- (void) someMethod {
   AnObject* myObj = [self.delegate.arr objectAtIndex:8];
   [self.delegate doThis];
}

Doing that way, A must import B, and B must import A.

If B do not import A (with just @class A), there is a compile error for the used attribute from A.
If B imports A, there is a compile error on the ClassA* delegateline.

Why do I have those compile errors? Doesn't #import protect again recursive calls ?

I don't need a solution to solve that problem, I know how I may do this.
But I wonder why my #import cause those problems. These are not #includes...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

写下不归期 2024-12-14 10:20:06

在 .h 文件中,更喜欢 @class 而不是 #import。然后可以将两者导入到 .m 实现文件中。

// ClassA.h -------------------------------
@class ClassB;
@interface ClassA : NSObject {
    ClassB* subController;
}

- (void) doThis;

// ClassB.h -------------------------------
@class ClassA;
@interface ClassB : NSObject {
    ClassA* delegate;
}

// ClassB.m -------------------------------
#import "ClassA.h"
#import "ClassB.h"

@implementation ClassB

- (void) someMethod {
   AnObject* myObj = [self.delegate.arr objectAtIndex:8];
   [self.delegate doThis];
}

使用 @class 语句而不是 #import 还可以减少依赖性并使其余的语句更加清晰。它还可以加快编译时间。

In .h files prefer @class to #import. Both can then be imported in the .m implementation files.

// ClassA.h -------------------------------
@class ClassB;
@interface ClassA : NSObject {
    ClassB* subController;
}

- (void) doThis;

// ClassB.h -------------------------------
@class ClassA;
@interface ClassB : NSObject {
    ClassA* delegate;
}

// ClassB.m -------------------------------
#import "ClassA.h"
#import "ClassB.h"

@implementation ClassB

- (void) someMethod {
   AnObject* myObj = [self.delegate.arr objectAtIndex:8];
   [self.delegate doThis];
}

Using @class statements instead of #import also reduces dependencies and makes the remaining ones more clear. It can also speed up compile times.

﹎☆浅夏丿初晴 2024-12-14 10:20:06

为什么我会出现这些编译错误? #import 不会再次保护递归调用吗?

#import 可防止重复将相同标头导入同一模块,无论是否通过循环包含/导入。它通过不让您这样做来防止这种情况:只有标头的第一个 #import 有效;同一标头的后续#import将被忽略。

在循环#include 的情况下,预处理器会绕圈数次,然后在进行编译之前构建失败。使用#import 可以防止预处理器陷入困境并让预处理器成功,但循环-#import 代码充其量仍然是狡猾的,通常无法编译。

那么,就看你的具体情况了。

对于您在问题中显示的代码, @class 将在一个或两个标头中工作,实际上您应该在两个标头中使用它。您还需要#import两个 .m 文件中的两个标头。

如果 B 不导入 A(仅使用 @class A),则 A 中使用的属性会出现编译错误。

如果您的意思是“在我使用 ClassA * 类型的属性的每个点上都会出现编译错误””,那么是的:您无法与该对象通信,因为您尚未导入其接口,因此编译器不知道您可以向 ClassA 实例发送哪些消息。这就是为什么你需要导入它的接口。

如果 B 导入 A,则 ClassA* 委托线上会出现编译错误。

如果两个标头相互导入,那么就会出现以下情况:如果

ClassA.m:
    ClassA.h
        ClassB.h
            ClassA.h (ignored because this was already imported by ClassA.m)
ClassB.m:
    ClassB.h
        ClassA.h
            ClassB.h (ignored because this was already imported by ClassB.m)

一个接口在另一个接口之前,而另一个接口在其之前,则此操作无法工作。这就是您正在陷入的循环——#import 存在的目的就是要打破这个循环。 #include 允许圆,从而楔入:

ClassA.m:
    ClassA.h
        ClassB.h
            ClassA.h
                ClassB.h
                    ClassA.h
                        ClassB.h
                            ClassA.h
                                ClassB.h
                                    ClassA.h
                                        ClassB.h
                                            ClassA.h
                                                ClassB.h
                                                    (fails at some point)

因此 #import

因此,您无法从另一个导入每个标头。因此@class

但您仍然需要从每个模块导入每个标头。事实上,这正是您需要做的:在每个标头中使用 @class 并在每个模块。

Why do I have those compile errors? Doesn't #import protect again recursive calls ?

#import protects against repeatedly importing the same header into the same module, whether by circular includes/imports or not. It protects against that by not letting you do it: Only the first #import of a header works; subsequent #imports of the same header are ignored.

In a circular #include situation, the preprocessor would go around the circle some number of times and then fail the build before you even get to compilation. Using #import prevents the preprocessor from getting wedged and lets the preprocessor succeed, but circular-#import code is still dodgy at best and usually will not compile.

So, on to your specific situation.

For the code you showed in your question, @class will work in either or both headers, and indeed you should use it in both. You'll also need to #import both headers in both .m files.

If B do not import A (with just @class A), there is a compile error for the used attribute from A.

If you mean “there is a compile error at each point where I use that attribute of type ClassA *”, then yes: You can't talk to that object because you haven't imported its interface, so the compiler doesn't know what messages you can send to a ClassA instance. That's why you need to import its interface.

If B imports A, there is a compile error on the ClassA* delegateline.

If both headers import each other, then you have this:

ClassA.m:
    ClassA.h
        ClassB.h
            ClassA.h (ignored because this was already imported by ClassA.m)
ClassB.m:
    ClassB.h
        ClassA.h
            ClassB.h (ignored because this was already imported by ClassB.m)

There is no way this can work without one interface preceding the other without the other interface preceding it. That's the circle you're running into—the circle that #import exists to break. #include allows the circle, and thereby gets wedged:

ClassA.m:
    ClassA.h
        ClassB.h
            ClassA.h
                ClassB.h
                    ClassA.h
                        ClassB.h
                            ClassA.h
                                ClassB.h
                                    ClassA.h
                                        ClassB.h
                                            ClassA.h
                                                ClassB.h
                                                    (fails at some point)

Hence #import.

So you cannot import each header from the other. Hence @class.

But you still need to import each header from each module. That is, in fact, exactly what you need to do: Use @class in each header and use #import (on both headers) in each module.

笑看君怀她人 2024-12-14 10:20:06

声明可以避免此编译投诉

@class ClassB;

通过在 .h 文件中 。然后可以将 ClassB.h 包含到 .m 文件中。

所以你在这一点上是对的。与都市神话相反,#imports 的工作方式与 #includes 非常相似,因为编译器必须检查文件。

请参阅(重复?)针对你的哲学问题提出问题。

This compile complaint can be avoided by declaring

@class ClassB;

in the .h file. The ClassB.h can then be included into the .m file.

So you are right on that one. Contrary to urban myth, #imports work pretty much like #includes in the sense that the compiler has to check the file.

See this (duplicate?) question for your philosophical problem.

别低头,皇冠会掉 2024-12-14 10:20:06

我认为您会发现 #import 仅在已经成功包含一次后才能防止多次包含,可以这么说。

即,在您的情况下,在要求再次导入之前它尚未成功导入 classa.h,因此它会这样做。

I think you'll find that #import only protects against multiple inclusion once it has already been successfully included once, so to speak.

ie, in your case, it hasn't successfully imported classa.h before it is asked to import it again, so it does so.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文