I have a problem with operator ->
and Objective-C.
I want to have C++ wrapper over ObjC class.
So I've created my class:
@interface User : NSObject
@property (nonatomic, copy) NSString *name;
@end
And wrapper class as well:
class UserWrapper {
User *_user;
// ctors, accessors, etc.
operator User *(){
return _user;
}
User *operator->(){
return _user;
}
};
When I try to access backing object via operator User*
it works good:
UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", [wrapper name]);
But when I try to access this object via operator ->
UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", wrapper->name);
I have the following error:
Property 'name' found on object of type 'User *'; did you mean to access it with the "." operator?
It seems that my understanding of operator ->
is wrong.
Does somebody have an explanation about what I'm doing wrong, and how to fix this issue?
Maybe there is another way to access backing object directly?
In C, C++, and Objective-C a->b
means to dereference a
and access the member b
. In C and C++ it's identical to but more straightforward than (*a).b
.
Your implementation of ->
would therefore be correct if User
had a member called name
, but it doesn't. If you've written no other code at all, your User
has an instance variable called _name
and a setter and a getter called name
and setName:
. In Objective-C, this syntax:
value = object.name;
is equivalent to this syntax:
value = [object name];
i.e. that's compiled as a method dispatch that invokes the getter. Similarly, this:
object.name = value;
is equivalent to:
[object setName:value];
i.e. that's compiled as a method dispatch that invokes the setter. In neither case are you accessing the instance variable. In both cases you're calling the setter and getter. If you wanted you could implement User
not to have an instance variable backing name
, putting it somewhere else entirely, or to convert it to and from some other form.
The clue is that the following is valid Objective C syntax:
User *object = [[User alloc] init];
object.name;
In C and C++ the dot operator doesn't work with pointers.
It's simply not normal to expose direct member variable access in Objective-C. For a proper wrapping you'd need to write actual getters and setters for each property. The hack approach would be something like:
@interface User: NSObject
{
@public
NSString *name;
}
@property (nonatomic, copy) NSString *name;
@end
[...]
@implementation User
@synthesize name;
@end
Which would:
name
;name
;->
.Direct instance variable manipulation is really a very bad idea though, both from a design and therefore a maintainability point of view, and in terms of allowing you to use other Objective-C features like key-value observing.