In Objective-C++, you can call methods from either language in C++ code and in Objective-C methods. Pointers to objects in either language are just pointers, and as such can be used anywhere. For example, you can include pointers to Objective-C objects as data members of C++ classes, and you can include pointers to C++ objects as instance variables of Objective-C classes. Listing 11-1 illustrates this.
Listing 11-1 Using C++ and Objective-C instances as instance variables
/* Hello.mm |
* Compile with: g++ -x objective-c++ -framework Foundation Hello.mm -o hello |
*/ |
#import <Foundation/Foundation.h> |
class Hello { |
private: |
id greeting_text; // holds an NSString |
public: |
Hello() { |
greeting_text = @"Hello, world!"; |
} |
Hello(const char* greeting_text) { |
greeting_text = [NSString stringWithUTF8String:greeting_text]; |
} |
void say_hello() { |
printf("%s\n", [greeting_text UTF8String]); |
} |
}; |
@interface Greeting : NSObject { |
@private |
Hello *hello; |
} |
- (id)init; |
- (void)dealloc; |
- (void)sayGreeting; |
- (void)sayGreeting:(Hello*)greeting; |
@end |
@implementation Greeting |
- (id)init { |
if (self = [super init]) { |
hello = new Hello(); |
} |
return self; |
} |
- (void)dealloc { |
delete hello; |
[super dealloc]; |
} |
- (void)sayGreeting { |
hello->say_hello(); |
} |
- (void)sayGreeting:(Hello*)greeting { |
greeting->say_hello(); |
} |
@end |
int main() { |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
Greeting *greeting = [[Greeting alloc] init]; |
[greeting sayGreeting]; // > Hello, world! |
Hello *hello = new Hello("Bonjour, monde!"); |
[greeting sayGreeting:hello]; // > Bonjour, monde! |
delete hello; |
[greeting release]; |
[pool release]; |
return 0; |
} |
As you can declare C structs in Objective-C interfaces, you can also declare C++ classes in Objective-C interfaces. As with C structs, C++ classes defined within an Objective-C interface are globally-scoped, not nested within the Objective-C class. (This is consistent with the way in which standard C—though not C++—promotes nested struct definitions to file scope.)
To allow you to conditionalize your code based on the language variant, the Objective-C++ compiler defines both the __cplusplus and the __OBJC__ preprocessor constants, as specified by (respectively) the C++ and Objective-C language standards.
As previously noted, Objective-C++ does not allow you to inherit C++ classes from Objective-C objects, nor does it allow you to inherit Objective-C classes from C++ objects.
class Base { /* ... */ }; |
@interface ObjCClass: Base ... @end // ERROR! |
class Derived: public ObjCClass ... // ERROR! |
Unlike Objective-C, objects in C++ are statically typed, with runtime polymorphism available as an exceptional case. The object models of the two languages are thus not directly compatible. More fundamentally, the layout of Objective-C and C++ objects in memory is mutually incompatible, meaning that it is generally impossible to create an object instance that would be valid from the perspective of both languages. Hence, the two type hierarchies cannot be intermixed.
You can declare a C++ class within an Objective-C class declaration. The compiler treats such classes as having been declared in the global namespace, as follows:
@interface Foo { |
class Bar { ... } // OK |
} |
@end |
Bar *barPtr; // OK |
Objective-C allows C structures (whether declared inside of an Objective-C declaration or not) to be used as instance variables.
@interface Foo { |
struct CStruct { ... }; |
struct CStruct bigIvar; // OK |
} ... @end |
Objective-C++ similarly strives to allow C++ class instances to serve as instance variables. This is possible as long as the C++ class in question (along with all of its superclasses) does not have any virtual member functions defined. If any virtual member functions are present, the C++ class may not serve as an Objective-C instance variable.
#import <Cocoa/Cocoa.h> |
struct Class0 { void foo(); }; |
struct Class1 { virtual void foo(); }; |
struct Class2 { Class2(int i, int j); }; |
@interface Foo : NSObject { |
Class0 class0; // OK |
Class1 class1; // ERROR! |
Class1 *ptr; // OK—call 'ptr = new Class1()' from Foo's init, |
// 'delete ptr' from Foo's dealloc |
Class2 class2; // WARNING - constructor not called! |
... |
@end |
C++ requires each instance of a class containing virtual functions to contain a suitable virtual function table pointer. However, the Objective-C runtime cannot initialize the virtual function table pointer, because it is not familiar with the C++ object model. Similarly, the Objective-C runtime cannot dispatch calls to C++ constructors or destructors for those objects. If a C++ class has any user-defined constructors or destructors, they are not called. The compiler emits a warning in such cases.
Objective-C does not have a notion of nested namespaces. You cannot declare Objective-C classes within C++ namespaces, nor can you declare namespaces within Objective-C classes.
Objective-C classes, protocols, and categories cannot be declared inside a C++ template, nor can a C++ template be declared inside the scope of an Objective-C interface, protocol, or category.
However, Objective-C classes may serve as C++ template parameters. C++ template parameters can also be used as receivers or parameters (though not as selectors) in Objective-C message expressions.
Last updated: 2008-02-05