1

我对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 ->是错误的。

有人对我做错了什么以及如何解决这个问题有解释吗?

也许还有另一种直接访问支持对象的方法?

4

1 回答 1

5

在 C、C++ 和 Objective-C中,a->b意味着取消引用a和访问成员b。在 C 和 C++ 中,它与(*a).b.

因此,如果有一个名为 的成员,您的实现->将是正确的,但事实并非如此。如果您根本没有编写任何其他代码,那么您有一个名为的实例变量和一个名为and的 setter 和一个 getter 。在 Objective-C 中,这种语法:UsernameUser_namenamesetName:

value = object.name;

等效于以下语法:

value = [object name];

即,它被编译为调用getter 的方法调度。同样,这个:

object.name = value;

相当于:

[object setName:value];

即,它被编译为调用setter 的方法调度。在这两种情况下,您都不会访问实例变量。在这两种情况下,您都在调用 setter 和 getter。如果您希望您可以实现User不具有实例变量 backing name,将其完全放在其他地方,或者将其转换为其他形式或从其他形式转换。

线索是以下是有效的 Objective C 语法:

User *object = [[User alloc] init];
object.name;

在 C 和 C++ 中,点运算符不适用于指针。

在 Objective-C 中直接暴露成员变量访问是不正常的。为了正确包装,您需要为每个属性编写实际的 getter 和 setter。hack 方法类似于:

@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 特性(如键值观察)方面。

于 2013-06-05T05:20:25.757 回答