2010-04-30 66 views

回答

7

不能合理使用作为实例变量的引用,因为没有办法来初始化实例变量和引用不能被重新插拔一下。

另一种可能是简单地使用(可能是智能)指针来代替。

,让你更接近C++的另一种可能性 - 样的行为是使用PIMPL风格的成员你的C++成员:

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 
+0

是的,就是这样! – 2010-04-30 17:39:09

+0

我不明白为什么你不只是存储一个指向SomeClass本身的指针。引用和指针之间的区别(大部分)是您的界面完美传输的语义之一。看到我的答案。 – Sebastian 2015-08-24 10:53:15

+0

@Sebastian如果你只有一个成员初始化(你多久只有一个成员?),这是没有意义的。如果您初始化多个成员并希望返回适当的确定性行为,这会变得很有趣。 FWIW,我提到了指针和这种方法作为可能的选择。 – 2015-08-24 12:18:48

0

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

+0

不是真的 - 'reference_wrapper '没有默认的构造函数,你不能初始化实例变量。 – 2010-04-30 16:57:30

0

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

话又说回来,如果你只需要存储一个成员,你不能用无论是结构还是这个包装要越过指针太大的优势。 (感谢乔治!)

我用乔治的回答为出发点的例子:

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

+0

为什么不直接在这里存储(可能是智能)指针实例?在这种情况下,我不认为这个包装会给你带来什么。 – 2014-04-02 11:27:31

+0

为什么不呢。想想看,在实际上和例子一样简单的情况下,我通常只是存储一个指针。 – 2014-04-02 14:07:02

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

+0

如果您可以修改需要您断言/检查一次的选项,那么断言A中的每个成员似乎都很麻烦并且容易出错。 – 2015-08-24 12:25:39

+0

这与断言您的pimpl指针在每个成员中仍然有效没有什么不同。也许它太偏执了,但它适用于这两种解决方案。 – Sebastian 2015-08-24 13:11:00