Objective-C ++和operator - >

时间:2013-06-05 04:38:27

标签: c++ objective-c clang objective-c++ clang++

我遇到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 ->的理解似乎是错误的。

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

也许有另一种直接访问后备对象的方法?

1 个答案:

答案 0 :(得分:5)

在C,C ++和Objective-C中a->b表示取消引用a并访问成员b。在C和C ++中,它与(*a).b相同但更直接。

如果->有一个名为User的成员,那么name的实施将是正确的,但事实并非如此。如果您根本没有编写任何其他代码,则User会有一个名为_name的实例变量,以及一个名为namesetName:的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;
  • 为属性创建一个setter和getter,也称为name;
  • 确保setter和getter使用属性的实例变量;
  • 还通过->公开实例变量以供直接访问。

直接实例变量操作实际上是一个非常糟糕的想法,无论是从设计还是从可维护性的角度来看,以及允许您使用其他Objective-C功能(如键值观察)。