Yesterday, I came across the following strange behavior. It seems like a compiler error for me or is there something I missed? I exchanged Facebook Connect classes for iPhone Objective-C with Objective-C classes in C ++ so that they can be used more conveniently from our own OpenGL / C ++ code.
The following code shows the problem. In the first version below, the compiler compiles, but confuses vtables, and therefore the wrong method is called. In the second option, we get a compiler error that indicates that gcc is confused.
Comments try to explain the situation in more detail.
#include <iostream>
#import <Foundation/Foundation.h>
class Foo_cpp {
public:
virtual void foo() = 0;
};
class Bar_cpp {
public:
virtual void bar() = 0;
};
@interface Foo_objc : NSObject {
Foo_cpp* foo_cpp_;
}
@end
@implementation Foo_objc
- (id)init:(Foo_cpp*)foo {
self = [super init];
if (self) {
foo_cpp_ = foo;
}
return self;
}
- (void) do_foo {
std::cout << "do_foo: ";
foo_cpp_->foo();
}
@end
@interface Bar_objc : NSObject{
Bar_cpp* bar_cpp_;
}
@end
@implementation Bar_objc
- (id)init:(Bar_cpp*)bar {
self = [super init];
if (self) {
bar_cpp_ = bar;
}
return self;
}
- (void) do_bar {
std::cout << "do_bar: ";
bar_cpp_->bar();
}
@end
class Main : public Foo_cpp, public Bar_cpp {
public:
Foo_objc* foo_;
Bar_objc* bar_;
Main() {
#if 0
foo_ = [[Foo_objc alloc] init:this];
bar_ = [[Bar_objc alloc] init:this];
[foo_ do_foo];
[bar_ do_bar];
#else
Foo_cpp* iface = this;
foo_ = [[Foo_objc alloc] init:iface];
Bar_cpp* iface2 = this;
bar_ = [[Bar_objc alloc] init:iface2];
[foo_ do_foo];
[bar_ do_bar];
#endif
}
~Main() {
delete foo_;
delete bar_;
}
virtual void foo() {
std::cout << "foo" << std::endl;
}
virtual void bar() {
std::cout << "bar" << std::endl;
}
};
int main() {
Main m;
}
The problem occurs with the iPhone SDK and Mac with g ++ and versions 4.0.1 and 4.2. Is there something I misunderstood or is this a bug in g ++?
UPDATE
, , . .
#include <iostream>
#import <Foundation/Foundation.h>
class Foo_cpp {
public:
virtual void foo() = 0;
};
class Bar_cpp {
public:
virtual void bar() = 0;
};
@interface Foo_objc : NSObject {
Foo_cpp* foo_cpp_;
}
@end
@implementation Foo_objc
- (id)init:(Foo_cpp*)foo {
self = [super init];
if (self) {
foo_cpp_ = foo;
}
return self;
}
- (void) do_foo {
std::cout << "do_foo: ";
foo_cpp_->foo();
}
@end
@interface Bar_objc : NSObject{
Bar_cpp* bar_cpp_;
}
@end
@implementation Bar_objc
- (id)init:(Bar_cpp*)bar {
self = [super init];
if (self) {
bar_cpp_ = bar;
}
return self;
}
- (void) do_bar {
std::cout << "do_bar: ";
bar_cpp_->bar();
}
@end
class Main : public Foo_cpp, public Bar_cpp {
void foo() {
std::cout << "foo" << std::endl;
}
void bar() {
std::cout << "bar" << std::endl;
}
};
int main() {
Main* m = new Main;
#if 0
Foo_objc* fo = [[Foo_objc alloc] init:m];
Bar_objc* bo = [[Bar_objc alloc] init:m];
#else
Foo_objc* fo = [[Foo_objc alloc] init:(Foo_cpp*)m];
Bar_objc* bo = [[Bar_objc alloc] init:(Bar_cpp*)m];
#endif
[fo do_foo];
[bo do_bar];
}
2
init: Fooobjc Barobjc initfoo: initbar: , , . , Objective-C ?