无法弄清楚“警告:不兼容的Objective-C类型” [英] Can't figure out 'warning: incompatible Objective-C types'

查看:110
本文介绍了无法弄清楚“警告:不兼容的Objective-C类型”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个NSObject子类实现 - (id)initWithRootElement:(MyElement *)e 方法。 NSXMLDocument具有采用NSXMLElement的相同方法。当我编译时,我得到以下警告:

I have a subclass of NSObject that implements an -(id)initWithRootElement:(MyElement *)e method. NSXMLDocument has an identical method that takes an NSXMLElement. When I compile, I get the following warning:

警告:不兼容Objective-C类型的结构MyElement *',预期'struct NSXMLElement *当从不同的Objective-C类型传递'initWithRootElement:'的参数1时

在这种情况下,我使用Clang + LLVM SnowLeopard与Xcode 3.2.1,但这也发生在GCC 4.2对豹和SnowLeopard。

In this case, I'm compiling with Clang + LLVM on SnowLeopard with Xcode 3.2.1, but this also happens with GCC 4.2 on both Leopard and SnowLeopard.

我不明白是为什么它为我的直接警告NSObject子类NSXMLDocument必须先从NSXMLNode继承吗?应该不知道 - (id)initWithRootElement:(NSXMLElement *)e 只适用于与我的类无关的NSXMLDocument?我可以理解,如果我试图重载的方法,但我不是。请告诉我我不会疯了...

What I don't understand is why it's throwing a warning for my direct NSObject subclass when NSXMLDocument has to inherit from NSXMLNode first? Shouldn't it know that -(id)initWithRootElement:(NSXMLElement *)e only applies to NSXMLDocument which has nothing to do with my class? I could understand if I was trying to overload the method, but I'm not. Please tell me I'm not going crazy...

#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSXMLElement.h>
// Importing this here causes the warning...
// #import <Foundation/NSXMLDocument.h>

typedef NSObject MyElement;

@interface TestClass : NSObject
{
}

- (id)initWithRootElement:(MyElement *)element;
@end

@implementation TestClass
- (id)initWithRootElement:(MyElement *)element { return nil; }
@end

// ...but here it doesn't
// #import <Foundation/NSXMLDocument.h>

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // No warning! Inheritance: NSXMLDocument -> NSXMLNode -> NSObject
    NSXMLElement *xmlElement = [[NSXMLElement alloc] initWithName:@"foo"];
    [[TestClass alloc] initWithRootElement:xmlElement];

    // warning: incompatible Objective-C types 'struct MyElement *', expected 'struct NSXMLElement *' when passing argument 1 of 'initWithRootElement:' from distinct Objective-C type
    MyElement *element = [[MyElement alloc] init];
    [[TestClass alloc] initWithRootElement:element];

    [pool drain];
    return 0;
}


推荐答案

Objective-C支持协变式声明。

Objective-C doesn't support covariant declarations.

NSXMLDocument中 initWithRootElement:的声明如下:

The declaration of initWithRootElement: in NSXMLDocument is as follows:

- (id)initWithRootElement:(NSXMLElement *)element;

这与您的声明不同:

- (id)initWithRootElement:(MyElement *)element;

因为参数类型不同。这会导致这行代码混乱(其中元素的类型 MyElement * ...

In that the argument types are different. This causes confusion in this line of code (where element is of type MyElement *...

[[TestClass alloc] initWithRootElement:element];

...因为 + alloc 的返回类型是 id 编译器不知道使用哪个方法;应该使用哪种类型的参数。

... because the return type of +alloc is id and, thus, the compiler doesn't know which method to use; which type of argument is to be expected.

当使用Objective-C开发面向Apple框架的代码时,

When developing code using Objective-C targeting Apple's frameworks, the rule of thumb is to never have different arguments declared for any given selector.

我有点惊讶,第一种情况不会警告。如果您有相当小的测试用例,请通过 http://bugreport.apple.com/ ,并将错误#附加到此问题(或我的回答)。

I'm slightly surprised that the first case doesn't also warn. It likely should. If you have a fairly minimal test case, file a bug via http://bugreport.apple.com/ and append the bug # to this question (or my answer).

这篇关于无法弄清楚“警告:不兼容的Objective-C类型”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆