C ++ reference type as an instance variable in Objective-C ++

C ++ reference types as instance variables are prohibited in Objective-C ++. How can I get around this?

+4
source share
4 answers

You cannot reasonably use references as an instance variable because there is no way to initialize instance variables, and links cannot be reinstalled.

An alternative would be to simply use (possibly smart) pointers.

Another possibility that brings you closer to C ++ behavior is to use a PIMPL style element for your C ++ members:

struct CppImpl { SomeClass& ref; CppImpl(SomeClass& ref) : ref(ref) {} }; @interface A : NSObject { CppImpl* pimpl; } - (id)initWithRef:(SomeClass&)ref; @end @implementation - (id)initWithRef:(SomeClass&)ref { if(self = [super init]) { pimpl = new CppImpl(ref); } return self; } // clean up CppImpl in dealloc etc. ... @end 
+7
source

George's first sentence is perfectly true:

You cannot reasonably use references as an instance variable because there is no way to initialize instance variables, and links cannot be reinstalled.

But I do not think his decision is the best.

The semantic difference between a pointer and a link is small. A reference is essentially a pointer that cannot be null. Therefore, it is certainly a good idea to use links in your interface to make it very obvious that nullptr not a valid initialization argument. But internally you can just save the pointer:

 @interface A : NSObject { SomeClass* p; } - (id)initWithRef:(SomeClass&)ref; @end @implementation A - (id)initWithRef:(SomeClass&)ref { if(self = [super init]) { p = &ref; } return self; } @end 

There is no longer (in the worst case: manual) memory allocation, no processing of resources at all, no additional indirectness, etc. Each member of A can simply say that p != nullptr .

+2
source

boost :: ref () can help?

0
source

A more general solution is to use reference_wrapper<T> instead of a custom structure. The end result is similar.

Then again, if you only need to save one element, you will not get many advantages over pointers, going either to the structure or to this shell. (Thanks, Georg!)

I used Georg's answer as a starting point for an example:

 // This bare interface can be used from regular Objective-C code, // useful to pass around as an opaque handle @interface A : NSObject @end // This interface can be shown to appropriate Objective-C++ code @interface A (Private) // @interface A () if it just for this class .mm file - (id)initWithRef:(SomeClass &)ref; @property (readonly, nonatomic) SomeClass &ref; @end @implementation A { reference_wrapper<SomeClass> *_refWrapper; } - (id)init { // and/or throw an exception return nil; } - (id)initWithRef:(SomeClass &)ref { self = [super init]; if(self) { _refWrapper = new reference_wrapper<SomeClass>(ref); } return self; } - (SomeClass &)ref { // reference_wrapper<T> is implicitly convertible to T& return *_refWrapper; // This would also work: // return _refWrapper->get(); } - (void)dealloc { delete _refWrapper; } @end 

This multi-header template is useful for passing an opaque descriptor in Objective-C code, giving Objective-C ++ the ability for multiple favorites (even if it's just an implementation of the objc class).

0
source

Source: https://habr.com/ru/post/1308482/


All Articles