4

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

4

4 回答 4

9

您不能明智地将引用用作实例变量,因为无法初始化实例变量并且无法重新定位引用。

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

另一种使您更接近 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
于 2010-04-30T16:55:31.063 回答
2

Georg 的第一句话是完全正确的:

您不能明智地将引用用作实例变量,因为无法初始化实例变量并且无法重新定位引用。

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

指针和引用之间的语义差异很小。引用本质上是一个不能为空的指针。因此,在您的界面中使用引用来明确 anullptr不是有效的初始化器参数当然是一个好主意。但在内部,您可以简单地存储一个指针:

@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.

于 2015-08-24T10:50:51.847 回答
0

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

于 2010-04-30T16:52:34.547 回答
0

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

再说一次,如果您只需要存储一个成员,那么通过使用 struct 或此包装器,您不会获得比指针更多的优势。(感谢乔治!)

我以 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 类的实现)。

于 2014-04-01T18:20:47.613 回答