复制构造函数未在Objective C ++代码中由Synthesis属性setter调用

时间:2010-09-04 16:00:53

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

我们都知道Objective-C ++是如何记录在案的。我找不到任何相关内容,但我也发现很难找到合适的明确搜索词。 所以,Stackoverflow来救援(我希望)!

我有一个C ++类,我在Objective-C(++)类中有一个实例(我启用了项目设置,可以调用构造函数/析构函数)。

这一切正常,直到我尝试通过@synthesize d属性公开实例。我将它设为assign属性(因为Obj-C保留计数不适用)。该属性似乎工作,除非我设置实例,我希望涉及复制构造函数。 我实际看到的是创建了一个临时实例(上的复制构造函数被调用) - 这是所有预期的。但是,ivar实例上的复制构造函数是 not 。这些值是“神奇地”设置的。我假设@synthesize d代码正在执行类似memcpy的操作作为最后一步。这适用于C struct,但对C ++ class不太有用,其中代码的正确性取决于正确调用的复制构造函数和赋值运算符。

有没有人更深入地研究过这个问题,让它发挥作用,或者确认无法在Obj-C(++)类中将C ++对象保存为ivars并且具有{{1}调用的复制构造函数} d属性设置者?

(如果有必要,我可以发布所有这些的示例代码 - 但即使是最小版本也是一个屏幕左右)。

2 个答案:

答案 0 :(得分:5)

嗯,如果我没有感到困惑,那么复制构造函数不会被调用是完全合理的。你是否期望ivar被魔法破坏和复制?我猜这是违反C ++规则的。如果合成的setter在概念上是

-(void)setFoo:(Foo)foo_{
    foo=foo_;
}

然后应该调用operator=,而不是复制构造函数。

那说operator=也没有被调用,无赖(10.6.4,gcc 4.2.1。)!这是示例代码:

#import <Foundation/Foundation.h>

class Foo{
    int a,b;
public:
    Foo():a(0),b(0){NSLog(@"default constructor for %p",this);}
    Foo(const Foo&foo):a(foo.a),b(foo.b){NSLog(@"copy constructor for %p",this);}
    Foo& operator=(const Foo& foo){
    NSLog(@"assignment operator for %p",this);
        a=foo.a;
        b=foo.b;
        return *this;
    }
};

@interface Bar:NSObject {
    Foo foo;
}
@property (assign) Foo foo;
@end

@implementation Bar
@synthesize foo;
@end

int main(){
    NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
    Bar* bar=[[Bar alloc] init];
    Foo foo;
    bar.foo=foo;
    [pool drain];
}

将其保存到boo.mm,我有:

$ g++ -fobjc-call-cxx-cdtors boo.mm -framework Foundation
$ ./a.out
2010-09-04 12:32:06.570 a.out[24352:903] default constructor for 0x10010cdc8
2010-09-04 12:32:06.572 a.out[24352:903] default constructor for 0x7fff5fbff7e0
2010-09-04 12:32:06.573 a.out[24352:903] copy constructor for 0x7fff5fbff7d0
$

现在,我有上面写的明确的setter而不是@synthesize Foo,我正确地

$ ./a.out
2010-09-04 12:42:22.206 a.out[24417:903] default constructor for 0x10010cdc8
2010-09-04 12:42:22.209 a.out[24417:903] default constructor for 0x7fff5fbff7e0
2010-09-04 12:42:22.210 a.out[24417:903] copy constructor for 0x7fff5fbff7d0
2010-09-04 12:42:22.210 a.out[24417:903] assignment operator for 0x10010cdc8

生成合成setter的clang源代码为this,请参阅GenerateObjCSetter。在那里,它最终测试是否需要C ++赋值运算符。我会说这是一个灰色地带,没有详细记录,但目前正在实施......

答案 1 :(得分:0)

具有属性的一般规则是,如果您需要特定的行为,即生成的默认样板文件无法为您提供,请为您的-setFoo:属性编写自己的foo方法,该方法可以满足您的需要。属性的自动合成是针对常见情况的,它们并不适用于所有地方。在这些情况下,请为酒店提供您自己的二传手或吸气剂。