我对 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 ->
的理解是错误的。
有人可以解释我做错了什么,以及如何解决这个问题吗?
也许还有另一种方法可以直接访问支持对象?
最佳答案
在C、C++和Objective-C中,a->b
表示解引用a
并访问成员b
。在 C 和 C++ 中,它与 (*a).b
相同但更直接。
如果 User
有一个名为 name
的成员,那么您对 ->
的实现将是正确的,但事实并非如此。如果您根本没有编写其他代码,那么您的 User
有一个名为 _name
的实例变量以及一个名为 name
和 设置名称:
。在 Objective-C 中,这种语法:
value = object.name;
等价于此语法:
value = [object name];
即它被编译为调用 getter 的方法分派(dispatch)。同样,这:
object.name = value;
相当于:
[object setName:value];
即它被编译为调用 setter 的方法分派(dispatch)。在这两种情况下,您都不会访问实例变量。在这两种情况下,您都在调用 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
; - 为属性创建 setter 和 getter,也称为
name
; - 确保 setter 和 getter 使用属性的实例变量;
- 还公开实例变量以通过
->
直接访问。
直接实例变量操作确实是一个非常糟糕的主意,无论是从设计和可维护性的角度来看,还是从允许您使用其他 Objective-C 功能(如键值观察)的角度来看。
关于c++ - Objective-C++ 和运算符 ->,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16931667/