Xcode4中的新LLVM编译器是否使类继承无法正常工作?

时间:2011-10-16 22:39:48

标签: iphone objective-c xcode xcode4 llvm

编辑:问题解决了!清洁并重新启动后它就消失了!我不知道是什么造成的!

这让我头疼了整整一天:

在Xcode 3.2中,一切都很出色。然后我切换到4.2,突然一个类继承不再起作用了。

我有一个班级TheSuperclassTheSubclass : TheSuperclass。为了简化测试,我真的像这样创建它们。没有比你在这里看到的更多的代码:

// TheSuperclass.h
@interface TheSuperclass : NSObject {

}

// subclasses must override this method
- (id)returnSomethingUseful;

@end

// TheSuperclass.m
#import "TheSuperclass.h"

@implementation TheSuperclass
- (id)returnSomethingUseful {
    NSLog(@"Dude, you have to override -returnSomethingUseful");
    return nil; // subclasses override this method!
}


- (id)init {
    if ((self = [super init])) {
            obj = [self returnSomethingUseful]; // TEST
        NSLog(@"TheSuperclass initialized: %@", obj);
    }
    return self;
}
@end

// TheSubclass.h
#import "TheSuperclass.h"

@interface TheSubclass : TheSuperclass {

}

@end

// TheSubclass.h
#import "TheSubclass.h"

- (id)returnSomethingUseful {
    NSLog(@"Correct method called!");
    return usefulObject;
}

TheSubclass *foo = [[TheSubclass alloc] init]; // remember: init of superclass calls the method
// Getting the NSLog: "Dude, you have to override -returnSomethingUseful"


id bar = [foo returnSomethingUseful]; // now call it directly on foo
// Getting the NSLog: "Correct method called!"

TheSuperclass声明了一个模板方法,即一个什么都不做的方法,返回nil并用于子类化:

- (id)returnSomethingUseful {
    NSLog(@"Dude, you have to override -returnSomethingUseful");
    return nil; // subclasses override this method!
}

TheSubclass中,我只是覆盖了该模板方法。当然,我将TheSuperclass中的实现归结为100%正确。没有错字。这是一个经过检查的事实。看起来像这样:

- (id)returnSomethingUseful {
    NSLog(@"Correct method called!");
    return usefulObject;
}

TheSuperclass的实现中,一段代码调用[self returnSomethingUseful]以便从模板方法中获取该对象。这是一个伟大的模式,我已经使用了很多。它总是像这样工作。

但是现在看来即使我创建了TheSubclass的实例,它总是调用WRONG方法。 TheSuperclass中的那个,而不是它应该的那个(当然这是最重要的方法)

我已经检查了至少100次!说真的,它是TheSubclass的一个实例。它调用TheSuperclass的init方法给我NSLogs。

现在真正奇怪的部分:当我从“外部”在我的TheSubclass对象上调用该方法时,它可以工作:

TheSubclass *foo = [[TheSubclass alloc] init];
id bar = [foo returnSomethingUseful];
// Getting the NSLog: "Correct method called!"

所以要强调它:当我从TheSuperclass的实现中调用[self returnSomethingUseful]时,它调用WRONG实现(它是超类之一,而不是子类中被覆盖的实现。

那我怎么解决这个问题呢?这可能来自哪里?这是运行时中的问题,可能是由编译器中的错误引起的吗?

3 个答案:

答案 0 :(得分:4)

LLVM显然能够正确实现简单的子类化。成千上万的程序每天都在使用它,所以如果你正在编写标准代码(不要尝试任何棘手或无证的代码),这不是一个需要解决的问题。以下是你应该做的事情:

  • 重新启动。 Xcode假装您不必在安装后重新启动。你根据我的经验。它在升级Xcode后解决了90%的问题。
  • 清理并重建。这不太可能修复它,因为从3.2到4.2无论如何都会将派生文件放在完全不同的位置。但值得一试。
  • 检查[self class]以确保您的确如此。
  • 确认您永远不会弄乱isa指针(很容易找到;在您的代码中搜索->isa)。
  • 检查init。这是做一些过于棘手的事情的最有可能的地方。确保你遵循简单的模式。
  • 导出最简单的问题形式并发布一些演示它的代码。根据您的描述,这应该可以在很少的代码行中完成。试图创建这个简化版本往往会告诉你你的错误在哪里。

答案 1 :(得分:2)

如果编译器搞砸了一些基本的东西,系统将无法启动。

init方法中断言该类,因为您有一个TheSuperclass实例或者拼写错误。

答案 2 :(得分:1)

术语是“覆盖”,而不是“覆盖”。

您还没有向我们展示足够的代码来了解问题所在。向我们展示两个类的-init方法,并向我们展示创建子类实例的位置。