Почему gcc предупреждает о несовместимом назначении структуры с помощью `self = [super initDesignatedInit];' вызов в производном классе?

У меня есть следующая настройка базового/производного класса в Objective-C:

@interface ASCIICodeBase : NSObject {
 @protected
  char code_[4];
}
- (Base *)initWithASCIICode:(const char *)code;
@end

@implementation ASCIICodeBase
- (ASCIICodeBase *)initWithCode:(const char *)code len:(size_t)len {
  if (len == 0 || len > 3) {
    return nil;
  }
  if (self = [super init]) {
    memset(code_, 0, 4);
    strncpy(code_, code, 3);
  }
  return self;
}
@end

@interface CountryCode : ASCIICodeBase
- (CountryCode *)initWithCode:(const char *)code;
@end
@implementation CountryCode
- (CountryCode *)initWithCode:(const char *)code {
  size_t len = strlen(code);
  if (len != 2) {
    return nil;
  }
  self = [super initWithCode:code len:len]; // here
  return self;
}
@end

В строке с пометкой «здесь» я получаю следующее предупреждение gcc:

warning: incompatible Objective-C types assigning 'struct ASCIICodeBase *', expected 'struct CurrencyCode *'

Что-то не так с этим кодом или я должен вернуть ASCIICodeBase id? Или, может быть, использовать приведение к строке «здесь»?


person gavinbeatty    schedule 12.03.2010    source источник


Ответы (2)


Вы должны привести возвращаемое значение к (CountryCode *). Метод возвращает значение типа ASCIICodeBase *, которое менее специфично, чем CountryCode *.

So:

self = (CountryCode *) [super initWithCode:code len:len];

Но на самом деле вам следует установить тип возвращаемого значения (id). Вот как это обычно делается в Objective-C.

person Philippe Leybaert    schedule 12.03.2010
comment
Понятия не имею. Когда вы участвуете в StackOverflow, я думаю, вы должны привыкнуть к этим трусливым отрицательным голосам. - person Philippe Leybaert; 12.03.2010
comment
Да, почему за это проголосовали? Это причина появления предупреждения. Люди странные. - person Jason Coco; 12.03.2010
comment
Сегодня с clang вам, вероятно, следует использовать возвращаемый тип instancetype вместо id (хотя clang автоматически заменяет id на instancetype, но семейство методов init, но не для всех других методов, подобных конструктору). - person Jean-Philippe Pellet; 06.03.2013

person    schedule
comment
Я ожидал поддержки ковариантного возвращаемого типа, к которой я привык в C++. (id) для таких сообщений базового класса. - person gavinbeatty; 14.03.2010
comment
Почему бы этим «авторелиз-конструкторам» и их друзьям не использовать instancetype вместо id? - person Jean-Philippe Pellet; 06.03.2013
comment
Кстати, похоже, clang теперь поддерживает ковариантные типы возврата для Objective C. - person Jean-Philippe Pellet; 06.03.2013
comment
Спасибо @Jean-PhilippePellet - это правильно. Когда я писал выше, этого не было. - person bbum; 06.03.2013