Objective-C++和operator - >

Ale*_*sov 1 c++ objective-c clang objective-c++ clang++

operator ->和Objective-C 有问题.

我想在ObjC类上使用C++包装器.

所以我创建了我的课程:

@interface User : NSObject

@property (nonatomic, copy) NSString *name;

@end
Run Code Online (Sandbox Code Playgroud)

还有包装类:

class UserWrapper {
    User *_user;
    //  ctors, accessors, etc.

    operator User *(){
        return _user;
    }

    User *operator->(){
        return _user;
    }
};
Run Code Online (Sandbox Code Playgroud)

当我尝试通过operator User*它访问后备对象时,效果很好:

UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", [wrapper name]);
Run Code Online (Sandbox Code Playgroud)

但是当我尝试通过访问此对象时 operator ->

UserWrapper wrapper([User new]);
[wrapper setName:@"alex"];
NSLog(@"%@", wrapper->name);
Run Code Online (Sandbox Code Playgroud)

我有以下错误:

Property 'name' found on object of type 'User *'; did you mean to access it with the "." operator?
Run Code Online (Sandbox Code Playgroud)

看来我的理解operator ->是错误的.

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

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

Tom*_*mmy 5

在C,C++和Objective-C中a->b意味着取消引用a和访问该成员b.在C和C++中它是相同的,但比直接更简单(*a).b.

->因此,如果User有一个成员调用name,那么您的实现将是正确的,但事实并非如此.如果你写的任何其他代码可言,你User有一个叫做的实例变量_name和setter和一个叫吸气namesetName:.在Objective-C中,这个语法:

value = object.name;
Run Code Online (Sandbox Code Playgroud)

等效于此语法:

value = [object name];
Run Code Online (Sandbox Code Playgroud)

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

object.name = value;
Run Code Online (Sandbox Code Playgroud)

相当于:

[object setName:value];
Run Code Online (Sandbox Code Playgroud)

即,它被编译为调用setter的方法调度.在这两种情况下,您都无法访问实例变量.在这两种情况下,你都在调用setter和getter.如果你想要你可以实现User不具备实例变量支持name,将其完全放在其他地方,或者将其转换为其他形式或从其他形式转换.

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

User *object = [[User alloc] init];
object.name;
Run Code Online (Sandbox Code Playgroud)

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

在Objective-C中公开直接成员变量访问是不正常的.要获得正确的包装,您需要为每个属性编写实际的getter和setter.黑客的方法是这样的:

@interface User: NSObject
{
    @public
       NSString *name;
}

@property (nonatomic, copy) NSString *name;
@end

[...]

@implementation User
@synthesize name;
@end
Run Code Online (Sandbox Code Playgroud)

这将:

  • 创建一个实例变量name;
  • 为一个属性创建一个setter和一个getter,也称为name;
  • 确保setter和getter使用属性的实例变量;
  • 还公开了实例变量以供直接访问->.

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