Development • 44:18
Objective-C++ combines the dynamic object model of Objective-C with the rich data abstraction facilities of C++ to create the ultimate "power tool" for many programming tasks. We explore the runtime model provided by Objective-C and then discuss Objective-C++ design goals and philosophy, and Xcode integration and support. We also cover issues in performance and compatibility. This session uses real-world programming examples and covers recent language additions to simplify C++ STL usage. This is an introductory to intermediate-level session.
Speaker: Steve Naroff
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
This is what we're going to explore today. I'd like to give you some context for this language because I feel it's important for understanding the design decisions, the trade-offs we made, and in fact, the roots of both of these languages. If you look at when C++ and Objective-C were born, they were both born in the mid-80s, roughly speaking, and C++ drew inspiration from Simula and Objective-C drew inspiration from Smalltalk.
And some of the terminology features and mindsets and, in fact, culture that surround these languages I hope to expose to give you some sense for why one language works one way, why another language solves a different set of problems, and why the combination of them is actually pretty exciting.
I also want to give you many examples because if we just talk in the abstract, you're not going to get a good feel for the language. The best way to learn the language is through examples. So the examples I'm going to be giving are from WebKit Safari. There are some examples from the Celestia application that you've seen.
There are some examples from our developer examples. So if you want to try some of these when you get home, you can go and look at the code that in fact we'll be presenting here. And lastly, I want to talk about some gotchas. It's a very complex language, and there are a few gotchas.
I don't think they affect too many people, but it's still relevant in the context of this talk. And lastly, I don't have this on the slide, but I'd love to interact with you folks for about 15, 20 minutes, so I'm hoping I could zoom through the presentation and customize it to what you guys want to know afterwards.
So, to cut to the chase, why isn't Cocoa written in C++? We wouldn't be here talking about the combined languages if, in fact, Cocoa was written in C++. And the simple answer is it doesn't meet Coco's needs. So before I explain why it doesn't meet Coco's needs, I'm going to try and go through what are Coco's needs, what are the language requirements, what are the runtime requirements that we have for Cocoa to set the stage for understanding the language.
Number one: easy to learn. Less is more. We want to be able to teach someone the language that Coco's written in in a week, max. I think we're going to cover most of the language here fairly well, and I think you'll get a good feel for Objective-C in a couple of hours, roughly.
But we want people to focus on the API, so we want to take the spotlight from the language and move it to the frameworks. That's one of the bigger reasons we wanted it to be easy to learn. We don't want you to focus or struggle with the language.
We want to embrace existing code. This has been part of the mindset for many years. That is, this isn't Java where we're trying to basically give you a clean new world that you have to conform to in a homogeneous way. We want you to be able to bring over your C code, your C++ code, and leverage it in the context of this very dynamic environment.
And lastly, and most importantly, we want a dynamic object model. The dynamic object model is what enables many of the cool features that you see in these presentations, whether it be Cocoa Bindings or Automator. Many of these very cool features are because we have dynamic plumbing underneath the covers that actually allows us to do some very, very interesting things.
And if you don't write frameworks for a living, you don't sometimes think about it. So if you're an application programmer, I'm hoping that if you haven't thought about some of these features, we're going to put them in a context that's going to make them much more interesting to you. So it's very important that we serve the frameworks and the interactive tools. What are the runtime requirements?
As most of you know, in the mid-80s, we weren't dealing with machines and memory models that were vast, as vast as today. For instance, Objective-C ran fairly well on two-megabyte workstations. And today, as you know, most workstations ship with 256 megabytes, 512, whatever, quite a bit more than it was designed for. So it's very clear that Objective-C, having been born in that age, scales nicely to today's machines.
It's very critical that when we ship new features that we don't break your code. Now, if you look at how many releases of Cocoa we've made and lots of frameworks, we've been very successful. In fact, I think we're the only operating system that I know of that is fairly object-oriented and hasn't, in fact, broken people with some regularity. So everything's shared, and we try not to break people.
We have a C-based API, and this, again, doesn't really affect you directly, but indirectly. That is, we feel strongly that Objective-C has to interact with other languages. So, for instance, the first two up there: Cocoa Java is a bridge that Apple supports. AppleScript Studio is another product that allows you from AppleScript to do Cocoa programming.
And then there's a whole bunch of third-party scripting languages: Python for Objective-C, Ruby, Cocoa, Perl. In fact, C# is being added to the list of languages that are going to be available to interact with Cocoa and bind with Objective-C. So, we're really excited to see third parties, in fact, integrate with this runtime, which we consider fairly flexible.
So to wrap it up, it's designed to serve the dynamic frameworks and tools and enables you to integrate your C code with Cocoa. But what this talk is about is Objective-C++, which is the same exact design point. It just enables you to integrate C++ code. So it's not as if the object modules are there to compete. They're there to work together. So now let's get back to why C++ doesn't meet Coco's needs. It's a strongly-typed static object model. This is one of the properties that makes it hard to evolve systems over time.
There's no runtime support for dynamic loading or reflection. Again, many features that we provide in our tools would not be possible with the standard C++ definition as many of you use it today. It is possible to expand the definition, but we view C++ as a standard language which we try not to extend.
And runtime model is fragile and compiler-dependent. This is a feature which has hurt C++ significantly. One of the reasons Java is so popular today is because it doesn't suffer from this. Shared libraries are critical for deploying code, and it contributes to this culture of code copying, where if you can't share something and not break it, you want to own it. You want to copy it in yourself so, in fact, you won't break. And, in fact, if you have many applications using many large frameworks and they're all copied, you can imagine what the memory footprint of your system would be like.
So, Objective-C++ design points. Peaceful coexistence, right? We want to use C++ as the base, and the parser has been modified to layer Objective-C atop C++. One of the smartest things I think we did was, many years ago, was we implemented Objective-C in the GNU compiler, and that work happened in '88, roughly. That work, along with the C++ work that was going on, enabled us to marry them with fairly low effort.
Both runtime systems are unchanged. Okay, the native ABI, the semantics, and the performance that you expect from C++ is what you get. It's not like we're changing the way you do virtual function dispatch or any other things in C++. We are letting C++ have its own turf and Objective-C have its own turf, and we think that works very nicely.
Now, subclassing across object models is not supported. Aggregation, we think, works great for this. In the early days when we used to present this language, people got really freaked out by that. They said, "God, you can't subclass? Is it really useful if you can't subclass?" Well, I think what's happened over time is people actually have learned through many iterations of designing object systems that inheritance is often not the best tool for performing something. So one of the things I'm going to talk about is how, in fact, Cocoa uses delegation, composition, aggregation as programming idioms and tools, which, in fact, again, make it a natural marriage because we don't require subclassing just by virtue of our dynamism.
So, subclassing isn't supported, so why don't we unify the object models? People sometimes ask, who haven't carefully considered some of the implications, "Why don't we just change C++ to work like Objective-C?" Well, there are systems that have been tried over time. SOM is one of them, the system object model that Apple and IBM worked on years ago, and even COM to some extent by Microsoft, that are actually systems designed to try and fix some of the problems with deploying C++ shared objects and the static object model. It turns out that because they were unsuccessful, we chose not to go that path, rather marry Objective-C and C++ as we've done.
So, let's go through the benefits. It's portable. It's amazing how even changing initialization order of the order in which constructors are run, that that breaks some of you guys out there. I work in the tools team where we're constantly looking at easier ways to port your apps and what headbutts you bump into, and initialization order isn't something that the standard dictates. That is, it says each system can do it however it wants.
Well, in fact, by the letter of the law, we work just fine. However, we, again, break some of your code because we don't do it in a specific way that, let's say, was born on Windows or Linux. So, again, we want to make things portable, and if initialization order is a problem, if we change the way dispatch work, believe me, we'd break all of you. So, performance.
The performance of an application is often dictated by the way it does dispatch. The fine-grain model, coarse-grain model of the object orientation. And Objective-C is just designed for more coarse-grain, mid-grain dynamism and not the very fine-grain stuff that people use C++ for. So, it would be naive to think that the same performance considerations that we apply to a dynamic, more coarse-grain object model apply to a fine-grain one.
And thirdly, we want to be pragmatic. Someone said to me outside the other day how one of the beauties of coming to this conference is that we're not just trying to make things portable. We're trying to make things more practical. And I think that's the key to the success of coming to this conference and seeing what Apple does and seeing Steve's keynote is how we're very good at finding the sweet spot. And that's why we're able to make releases on a yearly basis and show you guys cool stuff is because we find the sweet spot. And I think Objective-C C++ is a good example of that. It's pragmatic and it works.
So now let's go into the code section of the talk. Here is Hello World in four dialects. You have the first header file, std::io. You guys are all familiar with that. There's iostream, and then there's foundation. So you can see the standard printf::hello-world. You can see the C++ version. It's in all the C++ books. Then there's a couple more statements that give you the Objective-C version. Now, that string constant, for those of you who haven't seen Objective-C, a string constant preceded by an @ sign is a constant string object.
The compiler is responsible for creating it, and you can see it's initialized there. And then there's the combination of them, which is pretty seamless. So you have standard out taking as output the C string coming from the Objective-C string object, and then outputting the ++. So you can see that that's fairly easy to program.
So here's just how you compile it, just to show you that the file, the suffix is .mm. We don't have to get into the details of why it's called .mm, but it contains the mixed languages, and it's linking against the standard C++ library, which is a static library, not a shared library, and it's linking against the frameworks, the foundation framework. So pretty easy stuff.
Now, again, one detail. Right now we're shipping the standard C++ library as what we call an archive library, a non-shared library. So if you look at that executable, it's actually fairly big. It contains the whole standard C++ library contained within the Hello world. In a future release, we're going to be releasing a shared version of that.
Now I want to go through some just syntactic idioms, and I also want to go through some terminology. Here's what a class looks like, at interface. So let's get the at stuff out of the way. Why do we use at? The reason we prefix our keywords with at is we didn't want to break existing code. It's that simple. You know, some people get freaked out by the at sign, but that is the reason. It's we don't want to break code, because code contains interface. Code contains end.
And code contains other keywords that we wanted to publish. So that's why we use at. And it's a single inheritance model. So right there, the class is my class. The superclass is NSObject. For purposes of this discussion, Objective-C is single-rooted. It turns out that you can provide your own root class, but that's something for an advanced session that is a topic for another day. Oh, just briefly. Instance version. The term instance variable is a small talk jargon or terminology. In C++, if, in fact, some of you have just programmed in C++, you would know that as data members, right?
So members, data members, instance variables map into the same concept. So here we have a C type, an int, named X. We have an NSView named Y. And we have an Iostream named S. So you can see we have three different declarations here. That all contain different types.
Here are some methods. There are instance methods, and again, the term "method" comes from small talk. Instance method, class method. In C++, this would be member functions, and -- well, non-static member functions and member functions. And here we have a set-target method and a set-action method. Now, notice the colons. The colons would separate the key -- what's called the keyword argument from the actual type and the name of the argument. If you leave out the type in Objective-C, it means it's an ID.
We'll get into what ID means in a little while. So here we have a set-cell class. That's actually a class object. We'll get into that as well later. And selectors. Selectors are a unique name for a method. Okay, so they're like pointers to functions, except they represent the name, and they're unique per process. And we'll talk a little bit later about that.
So, so far we have a class interface, we have instance variables, we have methods. Here's an abstract type declaration. Objective-C decided to formalize the notion of abstract types years ago, and it's been something that's worked really well for us. So an abstract type is a type where you don't specify the instance variables, you don't specify the superclass, you just specify what the operations that are expected of the type are. So here's the NSDraggingInfo protocol. This is a set of methods which will all be given to the AppKit, and they will delegate to your object.
Here's an abstract type implementation. So you can see NSString. It inherits from NSObject, and it conforms to three protocols. So here's an example where Objective-C has single inheritance of implementation, but multiple inheritance of interface, which is a very common metaphor that we use in Cocoa and that works very well for us. So here, again, we have three different interfaces or protocols and a couple methods there.
So here is three different object declarations. In C++, you've probably never seen anything like ID. It's an object-oriented void star, pretty much. And it says, "Here is any object." Now, the difference is that object has metadata associated with it. So in fact, it's not as bad as a void star in that a void star, you know nothing about it except by looking at the source code. At runtime, you could actually infer what the type of object is.
Now, the second statement declaration there is an NSBrowser*. In Objective-C, when you type an object, that's there just for documentation. Okay? It tells the reader that that--any browser is an NSBrowser. It doesn't affect how the compiler will do binding. So dynamic dispatch, all the dynamic properties still apply even though it's been typed.
And the third declaration there says, "I have any object that conforms to the ns-dragging-info protocol," which is what I just showed in the previous slide. So that means any class that can conform to that protocol will be accepted by the compiler. What's really neat about this, again, is you don't have to know what type of object it is.
Now, you could even provide a list there. It's fairly uncommon, but just as you had a list within the class declaration context, you could have a list here as well. Another point, as contrast to Java, is Java integrates the abstract type namespace in with the class namespace. In Objective-C, they're separate. So you could have an NSObject class and an NSObject protocol and so on and so forth. So they're in separate namespaces.
Here we're going to go through message expressions. This is what you see the most of when you look at an Objective-C program. Here's the most simple one. We have my view, which is an object, and it's sending the timer update message. There's no arguments there. The second message expression there is any browser sent the set delegate object message.
That takes one argument. Notice the colon separates the name from the actual argument, in this case obj. The third one, a common idiom, is where the receiver is derived from a message. Here self is, I think the first time we've seen self, self is equivalent to this in C++, and it's sending the flush window message.
So now let's look at some hybrid message expressions. This first one is out of WebCore. It's sending the message keyboard UI. And you can see that it's accessing a static member function, bridge for widget. And in this case, this is active. So this is just a message expression I pulled out of WebCore to show you how easy it is to mix the two languages in message expressions. The second one is a bit more complicated.
There we have the adapter sending the set cookies for URL policy-based URL message, and you can see it's interspersed with arguments that are, in fact, member function calls. So fairly easy stuff. Again, a message expression is an expression. So just as you call in a function and you could provide expressions to each argument of the function, the same thing's true here. That's why the nesting works so nicely. There's nothing special about it.
There we go. So here are some more hybrid message expressions from Celestia. Here we have We're sending the star message to self. We're then dereferencing it, calling the setLuminosity member function. And we're passing it the float value from an Objective-C message expression. Again, you could see how natural the given play is. There's nothing really magic going on. And you could really see the two languages is collaborating and working well together here.
So the second one, we have NSNumber, and you can see the self star, and it's sending the getTemperature member function call. And the third one, we have simply a namespace named Astro, and there's just a standard C++ function that's embedded within the namespace Astro called lightYearsToParsecs, and it's being passed the float value.
Okay. Next thing I'd like to talk about is some dynamic idioms. Okay. Method categories are something we use pretty extensively in the application kit. It allows us to augment existing classes. It's something you don't see very commonly in other object-oriented languages. If you look at Common Lisp or you look at some other more dynamic languages, they're not called categories, but they allow you to do the same thing.
What they allow you to do is add operations to an existing class. So here's an example where on the app kit is adding some string drawing methods to the foundation string object. Likewise, here's an Objective-C++ category that Celestia adds to convert NSStrings to and from the standard strings.
So I want to show you briefly how it works, because I think many people who are new to some of the dynamic properties that Objective-C has, they get confused. So here are our three bodies of code. We have the foundation, where NSString lives. We have AppKit with a category that you just saw. We have Celestia with that category with the two methods.
What happens is, at runtime, the runtime links things up. And actually, when it loads the shared library, it says, oh, a category. Who are you associated with? And then it goes and looks up the class dynamically, and it sets the method tables accordingly so that you can basically extend the class methods in a fairly seamless way.
Here you see the NSString method table points to the string drawing method table, which points to-- so anything in the AppKit, all your applications get for free. If you want to have a private category, as Celestia does, that's a category that would be embodied with the actual executable for the application. That would obviously not be shared with other executables.
And what this allows is you to associate methods with other objects that work on their behalf. So for instance, these method tables aren't a part of NSView. They're not a part of the Celestial Galaxy. But they're methods that the Galaxy and the View would like to call on behalf of the string object. So why is all this interesting? It's because you don't have control of who instantiates objects all the time, right?
One of the things that frameworks are really good at is doing work on your behalf where you actually don't know what class is going to be sent the message. So we think this works really well, and in fact, people have used it in very interesting ways in various applications.
So another dynamic idiom, we have the setCellClass method. Basically, classes are first-class objects in Objective-C. You can reason about them. If you dynamically load code, you can find out what classes are a part of that code and invoke methods on them. setCellClass, you could reason about the superclass. These are all small talk idioms that we carried over into Objective-C.
And the is kind of predicate to basically ask, is this class a kind of another class? Now, notice the function there. The function allows you to take a string and convert it into an object. OK? That's another metaphor we use quite heavily, because the compiler can't always know or be told what class. Often, it's reading those things from external files, like your NIV file.
So here are methods of first-class objects as well. Here's a selector, the unique code. So if you want to compare selectors, you need to convert them. If you want to get a method signature, you need a selector. So in this case, it's already been converted. We send that message. Signatures contain the type. So if you're writing a tool or you're writing a framework and you want to know what types the method takes, the signature is really handy.
And here's an @Selector directive. @Selector is the equivalent of the function in this slide. The only difference is you're telling the compiler to do it, so it's a little more optimal because you know the name. In this case, it's alloc, so the compiler will get the unique code for the alloc method.
Delegation. Okay, this is something that we use in notifications. We use it in the target action paradigm in the application kit. We do things like, "Oh, if your object responds to this selector, well, send the windowDidMove message." The windowDidMove message is part of a protocol that we publish for tracking window operations.
And this is a perfect example of code that you don't often write, but is written all the time in the framework to collaborate with your objects. So, again, it's an interesting case where, until you see some of these idioms and metaphors and patterns, you don't appreciate them. And, again, this is one of the reasons when you write Cocoa programs, you don't find you're overwhelmed with subclassing, writing lots of different classes, and, in fact, ending up with some very highly structured or overly structured class hierarchy. It's fairly free-informed. It's more free-flowing.
So here's set target, set action. This is code from the interface builder paradigm, and this is in all of our controls. And then later on, once you have the target and the action, you can send the set action method accordingly. So this is the dynamic code that we find all over our frameworks that, again, simplifies your life.
Reflection. This is the hooks that support outlets, bindings, key-value coding, again, Cocoa bindings, which have been featured in many of the presentations. This is the low-level code that, in fact, supports those metaphors. So in this case, we have selector from string. It gets the selector, and then it asks response to. If it does respond to it, it performs the selector.
If no setter method has been found, a lower-level hook is provided to, in fact, look up the instance variable and set it directly in the object. So the simplification for the programmer is you don't have to write setter methods. The introspection, reflection that's provided with the runtime enables the tools to basically poke at your object and set up the connection, set up the binding without your intervention. It's nice to have the opportunity to write the setter, but that's not required.
So let's see, how are we doing on time here? So here are some examples. From OpenGL, this is on the developer disk. Here's an example of a more complete set of code where we have a value object that's a Q matrix there that's highlighted. And it's surrounded by an outlet right there from interface builder, mode, alpha. Again, this is on your disk.
Now, just because you're writing in Objective-C++, don't assume that all the classes have to be mixed. Right? Here's an example where, even though we saw some hybrid code in the previous slide, this class is pure C++. There's not any Objective-C in it. So a very, very common thing we see out there is people keeping a lot of their C++, let's say, portable and standard and not mixing the models everywhere, but in fact just doing it in very special control points. Right? It's very common to want to do a native interface in Cocoa and bring over your C++ engine, so to speak. And in fact, iChat's a good example. iChat is a wonderful Cocoa interface that the chat engine is actually in C++, and they work together via Objective-C++.
So here is just an example rotating the cube. You can see the one statement there that does the multiplication and then the extra Objective-C statements there to do the graphics and update the scene. Fairly straightforward stuff. Now, here's an interesting one. There was a class in this example that was largely C++, but there's a couple pure member functions there that were taking Objective-C objects, selectors, and, in fact, events.
So I've highlighted them for you. And you could see that these arguments are passed around as naturally as other arguments would be. So here's the handle event method. So you could see that it checks the event type, checks if it's a scroll wheel, and does the appropriate operations. Again, very, very straightforward.
Okay, so let's go to the next example, which is Core Audio. This is a little bit more complicated. This example, what's in orange are the C++ objects, and what's in blue are the Objective-C objects. So here we have a few vectors and a map that are C++ vectors and map from the standard C++ library that point off to Objective-C objects. So they're C++ containers that point off to Objective-C objects.
Here's the allocation method. So you can see that there's a couple Objective-C objects being allocated and initialized with the application delegate. And then there are several news, which are the vectors being instantiated. This is a good time to note that in Objective-C, all objects are dynamically allocated, okay, or by reference.
The only special object is NSString, which the compiler knows about. So it knows how to create static string constants. But all other Objective-C objects that you create are dynamically allocated. In C++, it's very common to use value objects, and we're going to talk a little bit more about that in a bit. But here, it so happens that the new is being used, and they're dynamic as well. So all the objects in this method are dynamic.
[Transcript missing]
So we just looked at C++ containers of Cocoa objects. I was alluding to the gotcha, which is it's a little bit sticky right now mixing the retain-release metaphor with C++. When the vector classes were developed, they obviously didn't know about Objective-C, right? So it's hard to expect them to know how to do this. And again, as I said before, both runtimes, both libraries don't know about each other. Fortunately, C++ provides some interesting hooks to be able to solve this problem.
I don't know if you were able to read the comments, but basically what's happening here is it's considered a no-no in Cocoa to transfer ownership across calls. So what I expected to-- when I was reading this method, I was expecting to see a release at the end. But it doesn't do a release. It passes the object on. And for purposes of this talk, if you're not familiar with retain-release, this is probably more than you need to know. But here, there's a manual release. So you saw that. And it's just confusing.
And I've talked to people who use the language, and they want to see this fixed. So one of the things that we're going to be doing is adding a smart pointer class to automate the retain-release. So for any of you who've tried to do this and have been confused by it, fortunately, C++ provides templates which allow you to customize the behavior of the vector. So for instance, by providing an ID pointer template, it allows us to solve this problem and write that code much more naturally and in a much less error-prone fashion.
So this is a feature that we expect to provide for Tiger. If not, it's actually fairly easy for you to implement this yourself. And it's not going to be a problem for you to do it yourself, if you need to do so in the short term. As I say in the slide, Boost Shared Pointer might even work for you off the shelf. If it doesn't, then you could adapt it to your needs. The next "gotcha" is exception handling.
Exception handling is supported in both languages. In C++, it's try-catch. In Objective-C, it's at-try, at-catch. But one of the confusing things here is if you look at these two calls here, one is sending the process message, and the other is timer update. You don't know whether these two calls are truly, like the first one, you don't know, is it C++ pure or is it hybrid, right?
The second one, you don't know, is this pure Objective-C message send? That is the method on the other end. Is it pure Objective-C or not, right? If you know that, then life's a little bit simpler. You can just wrap your C++ call with the try-catch and wrap your Objective-C message send with that try-catch.
Unfortunately, in this case, they're hybrid, which is why I used it as an example. So to solve this problem, it's straightforward, maybe initially non-obvious, but you basically wrap the first two calls in try-catch, and that's the C++ catch right there, and then you would wrap with that try-catch, okay? Now, fortunately, the way exceptions are used in Cocoa and C++, they're really used for exceptional conditions as errors, right?
So you don't find yourself having to write this type of code very often. Usually in Cocoa, in particular, you inherit an exception handler from NSApplication, and even if you decide to implement your own exception handling, you usually do it at a very high level of the application. Again, it's not handled for things like file not found.
So what I just talked about was sort of education. It isn't really a big gotcha. It's just something that you have to think about, more of a speed bump. This is a gotcha. This init method does something very bad. Basically, there's a value stack object that I've declared here. And as the comment says, the destructor for stack object will not be called automatically when that at throw happens.
The reason for this, unfortunately, is related to the fact that we're trying very hard to be binary compatible. So that when we added at try, at catch last year, we actually used set jump and long jump, which is what we had been using in Cocoa. And set jump and long jump do not know about the C++ runtime. So in fact, this is a gotcha by design, unfortunately. So what's the workaround?
The workaround, fortunately, is pretty straightforward. The workaround is fairly simple. All you do is call the destructor manually. Not the prettiest thing, but C++ allows you to do that, and it's possible. Again, hopefully you won't be dealing with this. This is more a matter of completeness and me being entirely upfront on some of the little things that exist. Again, I don't think this really will affect your life day to day.
Errors and warnings. This is probably the biggest gotcha that I hear complaints about, and it's because in C++, value objects are extremely common. And if you want to have a value object or an embedded object that's part of an Objective-C object, you get some really bad errors and warnings that basically tell you crazy things like the Vtable has virtual member functions and all kinds of crazy stuff that just doesn't make sense.
And it's because, again, the object runtimes, the two object runtimes, don't collaborate when dealing with this construct, mainly because at the time, we couldn't figure out how do we maintain the design point of keeping the runtimes distinct and solve this problem. We had incorrectly assumed that it was impossible.
Fortunately, we've figured out how to do it, and we'll be providing it in a future release. For now, there's a workaround. Right now, if you declare them reference and you instantiate them directly, it won't cause you any grief. Again, because new will do the correct thing. And as I said, this limitation is going to be removed and it'll just work as expected. So there are several people anxiously waiting for this one, I know, and hopefully it'll make their lives easier.
So I don't know if I went too fast here. We're going to fortunately have some nice about 20, 25 minutes left for Q&A, which I really value. And given the number of people here, I'm sure there's plenty of questions to ask about this. But here are some take-home points.
I think it's fairly clear that doing this stuff is fairly straightforward. The learning curve, if you're already a C++ programmer, is very low. Now, if you're not a C++ programmer and you're not an Objective-C programmer, this isn't the language for you, right? This is-- this-- you know, yeah, so.
Apple is using this extensively in almost every part of the company, whether it be our iApps, ProApps, iChat, Safari, and many third-party apps I've seen, and many that aren't public. They're using this extensively, and it's proven itself. So I feel really confident in advising you guys to use this, because I think it's going to save you time. And I think it's also going to expose people from the C++ language culture to new metaphors, new ways of building systems that I think will also benefit you.
I think both languages complement each other. I am constantly amazed at how they really don't get in each other's way. This wasn't clear when we did it many, many years ago. And, in fact, we were concerned about creating a monster. And I don't think we've done so. I think this is a very expressive tool.
And I think if C++ would have become the next C, which is what I thought 15 years ago when C++ was being developed, I was fairly convinced that it was going to be the next iteration of C, then this would seem even more natural. I think the only reason that it even seems to be a little controversial is because C++ didn't become formally the next C, even though it's the de facto next iteration of C. And I find most people doing serious applications of C++. And I think that's the reason why people who are doing this kind of application development are using it in some way. So documentation. And Matt Formica, he's our tools evangelist.