C ++引用类型作为Objective-C ++中的实例变量

时间:2010-04-30 16:49:48

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

Objective-C ++中禁止使用C ++引用类型作为实例变量。我该如何解决这个问题?

4 个答案:

答案 0 :(得分:8)

您无法合理地将引用用作实例变量,因为无法初始化实例变量,并且无法重新引用引用。

另一种选择可能是简单地使用(可能是智能的)指针。

让您更接近C ++的另一种可能性 - 就像为您的C ++成员使用PIMPL样式的成员一样:

struct CppImpl {
    SomeClass& ref;
    CppImpl(SomeClass& ref) : ref(ref) {}
};

@interface A : NSObject {
    CppImpl* pimpl;    
}
- (id)initWithRef:(SomeClass&)ref;
@end

@implementation    
- (id)initWithRef:(SomeClass&)ref {
    if(self = [super init]) {
        pimpl = new CppImpl(ref);
    }
    return self;
}
// clean up CppImpl in dealloc etc. ...
@end

答案 1 :(得分:2)

格奥尔格的第一句话是完全正确的:

  

您无法合理地将引用用作实例变量,因为无法初始化实例变量,并且无法重新引用引用。

但我认为他的解决方案是最好的解决方案。

指针和引用之间的语义差异很小。引用本质上是一个不能为空的指针。因此,在界面中使用引用肯定是一个好主意,使nullptr不是有效的初始化参数非常明显。但在内部,您只需存储指针:

@interface A : NSObject {
    SomeClass* p;    
}
- (id)initWithRef:(SomeClass&)ref;
@end

@implementation A
- (id)initWithRef:(SomeClass&)ref {
    if(self = [super init]) {
        p = &ref;
    }
    return self;
}
@end

没有(在最坏的情况下:手动)内存分配,根本没有资源处理,没有额外的间接等等.A的每个成员都可以简单地断言p != nullptr

答案 2 :(得分:0)

boost :: ref()可能有帮助吗?

答案 3 :(得分:0)

更通用的解决方案是使用reference_wrapper<T>而不是自定义结构。最终结果是类似的。

然后,再次,如果您只需要存储一个成员,那么通过使用struct或者这个包装器,你没有比指针更有优势。 (谢谢Georg!)

我使用Georg的答案作为例子的起点:

// This bare interface can be used from regular Objective-C code,
// useful to pass around as an opaque handle
@interface A : NSObject
@end

// This interface can be shown to appropriate Objective-C++ code
@interface A (Private) // @interface A () if it's just for this class's .mm file
- (id)initWithRef:(SomeClass &)ref;
@property (readonly, nonatomic) SomeClass &ref;
@end


@implementation A {
    reference_wrapper<SomeClass> *_refWrapper;    
}

- (id)init {
    // and/or throw an exception
    return nil;
}

- (id)initWithRef:(SomeClass &)ref {
    self = [super init];
    if(self) {
        _refWrapper = new reference_wrapper<SomeClass>(ref);
    }
    return self;
}

- (SomeClass &)ref {
    // reference_wrapper<T> is implicitly convertible to T&
    return *_refWrapper;
    // This would also work:
    // return _refWrapper->get();
}

- (void)dealloc {
    delete _refWrapper;
}

@end

这个多标题模式有助于传递Objective-C代码中的不透明句柄,同时为少数人提供Objective-C ++特性(即使它只是objc类的实现)。