我遇到operator ->
和Objective-C的问题。
我想在ObjC类上使用C ++包装器。
所以我创建了我的课程:
@interface User : NSObject
@property (nonatomic, copy) NSString *name;
@end
还有包装类:
class UserWrapper {
User *_user;
// ctors, accessors, etc.
operator User *(){
return _user;
}
User *operator->(){
return _user;
}
};
当我尝试通过operator User*
访问支持对象时,效果很好:
UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", [wrapper name]);
但是当我尝试通过operator ->
UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", wrapper->name);
我有以下错误:
Property 'name' found on object of type 'User *'; did you mean to access it with the "." operator?
我对operator ->
的理解似乎是错误的。
有人解释我做错了什么,以及如何解决这个问题?
也许有另一种直接访问后备对象的方法?
答案 0 :(得分:5)
在C,C ++和Objective-C中a->b
表示取消引用a
并访问成员b
。在C和C ++中,它与(*a).b
相同但更直接。
如果->
有一个名为User
的成员,那么name
的实施将是正确的,但事实并非如此。如果您根本没有编写任何其他代码,则User
会有一个名为_name
的实例变量,以及一个名为name
和setName:
的setter和一个getter。在Objective-C中,这种语法:
value = object.name;
等同于以下语法:
value = [object name];
即。这被编译为调用getter的方法调度。同样,这个:
object.name = value;
相当于:
[object setName:value];
即。这被编译为调用setter的方法调度。在这两种情况下,您都无法访问实例变量。在这两种情况下,你都在调用setter和getter。如果你想要,你可以实现User
不要拥有支持name
的实例变量,将其完全放在其他地方,或者将其转换为其他形式或从其他形式转换。
线索是以下是有效的Objective C语法:
User *object = [[User alloc] init];
object.name;
在C和C ++中,点运算符不适用于指针。
在Objective-C中公开直接成员变量访问是不正常的。要获得正确的包装,您需要为每个属性编写实际的getter和setter。黑客的做法是这样的:
@interface User: NSObject
{
@public
NSString *name;
}
@property (nonatomic, copy) NSString *name;
@end
[...]
@implementation User
@synthesize name;
@end
哪个会:
name
; name
; ->
公开实例变量以供直接访问。直接实例变量操作实际上是一个非常糟糕的想法,无论是从设计还是从可维护性的角度来看,以及允许您使用其他Objective-C功能(如键值观察)。