Классы С++ как переменные экземпляра класса Objective-C

99
12

Мне нужно смешать Objective-C и С++. Я хотел бы скрыть все объекты С++ внутри одного класса и сохранить все остальные равными Objective-C. Проблема в том, что я хочу, чтобы некоторые классы С++ были переменными экземпляра. Это означает, что они должны упоминаться в файле заголовка, который включается другими классами, а С++ начинает распространяться на все приложение. Лучшее решение, с которым я смог прийти, выглядит следующим образом:


#ifdef __cplusplus
#import "cppheader.h"
#endif

@interface Foo : NSObject
{
id regularObjectiveCProperty;
#ifdef __cplusplus
CPPClass cppStuff;
#endif
}

@end


Это работает. Файл реализации имеет расширение mm, так что он скомпилируется как Objective-C, смешанный с С++, #ifdef разблокирует С++-материал и там мы идем. Когда какой-то другой, чисто класс Objective-C импортирует заголовок, материал С++ скрыт, и класс не видит ничего особенного. Это похоже на взлом, есть ли лучшее решение?

спросил(а) 2009-06-29T10:04:00+04:00 11 лет, 3 месяца назад
1
Решение
122

Это звучит как классическое использование для интерфейса/@протокола. Определите протокол objective-c для API, а затем предоставите реализацию этого протокола, используя класс Objective-C ++. Таким образом, клиентам необходимо знать только протокол, а не заголовок реализации. Поэтому, учитывая первоначальную реализацию


@interface Foo : NSObject
{
id regularObjectiveCProperty;
CPPClass cppStuff;

}

@end


Я бы определил протокол


//Extending the NSObject protocol gives the NSObject
// protocol methods. If not all implementations are
// descended from NSObject, skip this.
@protocol IFoo <NSObject>

// Foo methods here
@end

и измените первоначальное объявление Foo на


@interface Foo : NSObject <IFoo>
{
id regularObjectiveCProperty;
CPPClass cppStuff;
}

@end


Клиентский код затем может работать с типом id<IFoo> и его не нужно компилировать как Objective-C ++. Очевидно, вы можете передать экземпляр Foo этим клиентам.

ответил(а) 2009-06-29T18:25:00+04:00 11 лет, 3 месяца назад
80

Недавно я столкнулся с этой проблемой. В моем случае протокол был излишним. Мне просто нужно было сохранить указатель на объект доступа к данным, который оказался объектом С++.


То, что я сделал, было объявить класс с переменной экземпляра void * и применить его, когда я использую его в методах экземпляра.

Это немного взломанный, но концептуально он очень похож на тип Objective-C id.

ответил(а) 2009-10-29T18:03:00+03:00 10 лет, 11 месяцев назад
57

Есть ли какая-то особая причина, по которой вы просто не можете использовать Objective С++? Просто переключите компилятор на Compile Sources As: Objective С++ (или переименуйте все исходные файлы с .cpp или .m на .mm). Затем вы можете свободно смешивать С++ и Objective C.


С++ начинает распространяться на весь Приложение



Какая проблема с этим? Если ваш Objective C-код выполняет только C/Objective C-код вообще, то он почти наверняка не будет затронут вообще, будучи скомпилированным как С++. Нет заметных проблем с производительностью или скоростью.


Единственные два недостатка, которые я нашел: вы не можете (пока) использовать статический анализатор clang для анализа С++; некоторый (относительно странный) код C не работает на С++, что иногда является проблемой при использовании стороннего кода C.

ответил(а) 2009-06-30T09:13:00+04:00 11 лет, 3 месяца назад
41

НЕ ДЕЛАЙТЕ ЭТО


Если вы выберете переменную экземпляра, это даст два отдельных шаблона переменных экземпляра для этого класса. Вы получите случайные разметки памяти по всему месту, потому что память, выделенная для объекта в половине случаев, будет слишком коротка. Вместо ifdefing из переменной экземпляра, forward-declare свой тип, например


struct CPPClass;

и указатель на него в ivar, тогда в ваших методах init/dealloc вызовите new/delete для создания объекта. Если у вас есть несколько объектов, вы можете создать структуру для хранения всех С++ ivars напрямую, а затем просто создать новую/удалить эту структуру.


См. эту тему для получения более подробной информации и дальнейших ссылок на информацию, включая подкаст, который подробно обсуждает ObjС++: Могу ли я отделить основную функцию и классы С++ от Objective-C и/или C в компиляции и ссылке?

ответил(а) 2015-02-12T14:10:00+03:00 5 лет, 7 месяцев назад
41

Вы можете обнаружить, что у вас есть проблемы с этим - из того, что я помню из ObjectiveС++, вы можете обнаружить, что конструктор и деструктор для вашего закрытого объекта С++ не будут вызваны.

ответил(а) 2009-07-28T15:50:00+04:00 11 лет, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема