Apple’s Objective-C compiler allows you to freely mix C++ and Objective-C code in the same source file. This Objective-C/C++ language hybrid is called Objective-C++. With it you can make use of existing C++ libraries from your Objective-C applications.
Mixing Objective-C and C++ Language Features
C++ Lexical Ambiguities and Conflicts
Limitations
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 13-1 illustrates this.
Note: Xcode requires that file names have a “.mm” extension for the Objective-C++ extensions to be enabled by the compiler.
Listing 13-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* initial_greeting_text) { |
greeting_text = [[NSString alloc] initWithUTF8String:initial_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 |
On Mac OS X 10.4 and later, if you set the fobjc-call-cxx-cdtors
compiler flag, you can use instances of C++ classes containing virtual functions and nontrivial user-defined zero-argument constructors and destructors as instance variables. (The fobjc-call-cxx-cdtors
compiler flag is set by default in gcc-4.2.) Constructors are invoked in the alloc
method (specifically, inside class_createInstance
), in declaration order immediately after the Objective-C object of which they are a member is allocated. The constructor used is the “public no-argument in-place constructor.” Destructors are invoked in the dealloc
method (specifically, inside object_dispose
), in reverse declaration order immediately before the Objective-C object of which they are a member is deallocated.
Mac OS X v10.3 and earlier: The following cautions apply only to Mac OS X v10.3 and earlier.
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 |
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.
There are a few identifiers that are defined in the Objective-C header files that every Objective-C program must include. These identifiers are id
, Class
, SEL
, IMP
, and BOOL
.
Inside an Objective-C method, the compiler pre-declares the identifiers self
and super
, similarly to the keyword this
in C++. However, unlike the C++ this
keyword, self
and super
are context-sensitive; they may be used as ordinary identifiers outside of Objective-C methods.
In the parameter list of methods within a protocol, there are five more context-sensitive keywords (oneway
, in
, out
, inout
, and bycopy
). These are not keywords in any other contexts.
From an Objective-C programmer's point of view, C++ adds quite a few new keywords. You can still use C++ keywords as a part of an Objective-C selector, so the impact isn’t too severe, but you cannot use them for naming Objective-C classes or instance variables. For example, even though class
is a C++ keyword, you can still use the NSObject
method class
:
[foo class]; // OK |
However, because it is a keyword, you cannot use class
as the name of a variable:
NSObject *class; // Error |
In Objective-C, the names for classes and categories live in separate namespaces. That is, both @interface foo
and @interface(foo)
can exist in the same source code. In Objective-C++, you can also have a category whose name matches that of a C++ class or structure.
Protocol and template specifiers use the same syntax for different purposes:
id<someProtocolName> foo; |
TemplateType<SomeTypeName> bar; |
To avoid this ambiguity, the compiler doesn’t permit id
to be used as a template name.
Finally, there is a lexical ambiguity in C++ when a label is followed by an expression that mentions a global name, as in:
label: ::global_name = 3; |
The space after the first colon is required. Objective-C++ adds a similar case, which also requires a space:
receiver selector: ::global_c++_name; |
Objective-C++ does not add C++ features to Objective-C classes, nor does it add Objective-C features to C++ classes. For example, you cannot use Objective-C syntax to call a C++ object, you cannot add constructors or destructors to an Objective-C object, and you cannot use the keywords this
and self
interchangeably. The class hierarchies are separate; a C++ class cannot inherit from an Objective-C class, and an Objective-C class cannot inherit from a C++ class. In addition, multi-language exception handling is not supported. That is, an exception thrown in Objective-C code cannot be caught in C++ code and, conversely, an exception thrown in C++ code cannot be caught in Objective-C code. For more information on exceptions in Objective-C, see “Exception Handling.”
© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-05-06)