Tuesday, December 23, 2008

Puzzling

The Objective-C 2.0 Programming Language on the iPhone Dev Docs under Mixing Objective-C and C++ states...

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.

Well, I did just that and it compiled/linked and ran.  Looking at the Instruments/Leaks all is well.  Hmmmn...so why does it work?  I took the bridge code I did yesterday and modified it to have a virtual member function in class Hello, and added another class StairwayToHeaven with a virtual member function.  Here's the code...


class StairwayToHeaven
{
public:
StairwayToHeaven()
{
printf("StairwayToHeaven:Ctor called.\n");
}

~StairwayToHeaven()
{
printf("StairwayToHeaven:dtor called.\n");
}

void PlayGame()
{
printf("StairwayToHeaven: Playing game.\n");
}

virtual void VirtualFunc(void)
{
printf("StairwayToHeaven: VirtualFunc called.\n");
}
};

class Hello
{
private:
id greeting_text;
StairwayToHeaven *pStairwayToHeaven;

public:
Hello()
{

greeting_text = @"Hello, world!";
pStairwayToHeaven = new StairwayToHeaven;
}

~Hello()
{
printf("Hello:dtor called\n");

delete pStairwayToHeaven;
}

Hello(const char* initial_greeting_text)
{
greeting_text = [[NSString alloc] initWithUTF8String:initial_greeting_text];

}

virtual void VirtualFunc(void)
{
printf("Hello: VirtualFunc called.\n");
}

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;
- (void) doVirtualFunc;

@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();
}

- (void) doVirtualFunc
{
hello->VirtualFunc();
}

@end

#import
#include "test.h"
#include
#include

int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// notice here...dynamic typing
std::vector testVector;
id szTest = @"'ello Gov'ner!";

// testing in new C++ casting works in mixed Obj-C/C++
float fTest = 9.0f;
int nTest = static_cast(fTest);
printf("nTest = %d\n", nTest);

// instantiate the Greeting class
Greeting *greeting = [[Greeting alloc] init];

// test to see if I can use STL
testVector.push_back(greeting);
testVector.push_back(szTest);
printf("number of objects in the vector = %d\n", testVector.size());

// get the "sayGreeting" method from the Greeting class
SEL action = @selector (sayGreeting);

short i = 0;
for(std::vector::iterator it = testVector.begin(); it != testVector.end(); it++)
{
printf("In vector loop = %d\n", i++);

// check to see if the object is our Greeting object
if( [*it respondsToSelector: action] == YES )
[*it sayGreeting];
else
printf("%s\n", [*it cString]); // it is our other object
}

// can also do C++ straight up
Hello *hello = new Hello("Bonjour, monde!");

// then mix it with Obj-C
[greeting sayGreeting:hello];
[greeting doVirtualFunc];

delete hello;
[greeting release];

[pool release];

return 0;
}

I'll post a question to the Objective-C listserv and see what folks say.

Object-C/C++ya!

No comments: