PDA

View Full Version : Objective-C virtual function question




ziyu4huang
Aug 2, 2006, 11:57 PM
Hi, I am a newbie of objective-c. Hopes someone can give me some question about the virtual function question.

I found in objective-c all fuction is virtual functin (in C++ term). And this turns out that it is impossbile to implement a special Bridge Design Pattern. (efficiently get private object from public pointer, and public pointer is not a real object). Is there any way to make an member function (or method) become non-virtual function just like default in C++ ?

Here is an example of C++ code that works.

class Foo {
public:
void foo(){
printf("Foo me %X\n", this);
}
};

int main(){
Foo* foo = (Foo*)malloc(1);
foo->foo();
}

-------------- but this code is not working in objective-c -------------
#include <objc/Object.h>

@interface Foo : Object
{
}
+ new;
- foo;
@end

@implementation Foo
+ new
{
self = [super new];
return self;
}
- foo
{
printf("Foo me %X\n", self);
}

@end

int main(){
{
Foo* foo = [Foo new];
[foo foo];
//this can work
}
Foo* foo = (Foo*)malloc(1);
[foo foo];
}



robbieduncan
Aug 3, 2006, 04:02 AM
Objective-C does not have a concept of "virtual" so there is no way of turning it off (at least that I know of).

slooksterPSV
Aug 3, 2006, 03:37 PM
You could combine C++ and objective-c (namely Objective-C++ right?) and do it like that. Just implement one for another and another for one.

E.g.

... //more up here
class myClass {
private:
int dataNum;
char *dataCharPtr;
public:
myClass () { .../*constructor stuff here*/ }
~myClass () { .../*destructor stuff*/ }
};


then create an objective-c class that can use that


...//more up here
@interface myClass2 : NSObject
{
myClass* class;
}

- (void) initClass;
- (void) allocClass;
@end

@implementation myClass2

- (void) initClass
{
class = new myClass;
}

- (void) allocClass
{
class = (myClass *)malloc(1);
}

@end

at least that's how I'd do it if I need to.

Does that work?

Catfish_Man
Aug 3, 2006, 04:08 PM
That's a really really bizarre syntax. I doubt you can duplicate it effectively in ObjC, *particularly* if you need access to self. It's simply impossible to fit a self pointer in one byte of memory.

mrichmon
Aug 3, 2006, 06:58 PM
I found in objective-c all fuction is virtual functin (in C++ term). And this turns out that it is impossbile to implement a special Bridge Design Pattern.

Methods on objects in Objective-C are not virtual functions, they are real functions.

Using a public pointer in C++ to provide access to a private field is a nasty way of implementing that kind of structure. A better way to do it is to implement a public getter method that provides access to the field. Using a getter it is very easy to implement the Bridge design pattern in Objective-C.

ziyu4huang
Aug 3, 2006, 07:57 PM
Methods on objects in Objective-C are not virtual functions, they are real functions.

Using a public pointer in C++ to provide access to a private field is a nasty way of implementing that kind of structure. A better way to do it is to implement a public getter method that provides access to the field. Using a getter it is very easy to implement the Bridge design pattern in Objective-C.
I am not familior terms in Objective-C, I just learn it two days, but I think
the all function in Objective-C is just like virtual funciton in C++, you
can try to modify my sample code of C++, see what's happening.

class Foo {
public:
virtual void foo(){
printf("Foo me %X\n", this);
}
};

----
the result will just like Objective-C, it crashed because the object pointer pass to member function is not a realy object, and hence we cannot get the function table of this object. That's why I call all function in Objective-C is virtual (in C++ term).

I reason why I need this is in C++, you can fake a pointer as an object without a problem(then translate to proper private object and value)
, but it seems not possbile in Objective-C.


for example in C++ I can do this.

class Foo {
void getValue(){
int index;
FooPvt* pvtObj;
PvtManager::get(pvtObj, index);
pvtObj->getValue(index);
}
}


class FooPvt {
void getValue(int index){
..../* real get value action*/
}
}
... With PvtManager I can get the reall private object and it's index from the fake object pointer. This is a special and fast Bridge Design Pattern.
I just don't know how to implement it in Objective-C

slooksterPSV
Aug 3, 2006, 09:14 PM
... With PvtManager I can get the real private object and it's index from the fake object pointer. This is a special and fast Bridge Design Pattern.
I just don't know how to implement it in Objective-C


class Foo {
void getValue(){
int index;
FooPvt* pvtObj;
PvtManager::get(pvtObj, index);
pvtObj->getValue(index);
}
}


class FooPvt {
void getValue(int index){
..../* real get value action*/
}
}

We can change it to this (not sure if it'll do the same thing):


@implementation Foo

- (void) getValue
{
int index;
FooPvt* pvtObj;
[PvtManager getObject:pvtObj atIndex:index]; //uh, what's PvtManager?
//
//I'd probably do pvtObj = [pvtObj self]; err... hmm that doesn't seem right
//
[pvtObj getValue:index];
}
@end


@implementation FooPvt

- (void) getValue:(int) index{
..../* real get value action*/
}

@end


...hmm that may not work for you... store all your objects in a global NSMutableArray or even just a plain NSArray and access the object through that way. You'll access the real object and modify it. If you need the memory location, it's handled by OS X. Otherwise, like I said, just integrate C++ and Objective-C


EDIT: it may be possible to leave this in:
PvtManager::get(pvtObj, index);

Krevnik
Aug 3, 2006, 10:39 PM
Methods on objects in Objective-C are not virtual functions, they are real functions.


I beg to differ, methods in Obj-C aren't quite real like one would expect. They behave just like virtual functions in C++ do, except you cannot make a 'pure virtual' function in Objective-C.

In C++, the default behavior is that if you cast a child class to its parent, the parent's methods are called when you call into it. This is not the case in Objective-C where you can call into any method that exists, and the actual class that was instanced will be used, since each object in Objective-C carries something similar to the virtual function table.

The problem I see with trying to implement a bridge design is that you cannot create a fake object, really. You can't force an Objective-C object's behavior onto random memory, because of things like the method tables. You can mask an object with another in this way, and you can use a protocol to help map up the two objects more easily, but it isn't going to behave quite the same way.

ziyu4huang
Aug 3, 2006, 11:44 PM
[code]
class Foo {
void getValue(){
int index;
FooPvt* pvtObj;
PvtManager::get(pvtObj, index);
pvtObj->getValue(index);
}
}


Sorry, I type it too fast, the code should be



class Foo {
void getValue(){
int index;
FooPvt* pvtObj;
PvtManager::get(this, pvtObj, index);
pvtObj->getValue(index);
}
}


class PvtManager
{
static void get(Foo* obj, FooPtv*& pvtObj, &index)
{
index = PublicObjAddrToIndex(obj);
pvtObj = PublicObjAddrToPvtObj(obj);
}
}

slooksterPSV
Aug 4, 2006, 04:52 AM
AFAIK that wouldn't work in just plain Objective-C, but if you combined Objective-C and C++ (Objective-C++) then you could do that with a little tweaking and modification.

HiRez
Aug 4, 2006, 08:01 AM
I don't really understand what is being asked for here. Could you explain what it is that you're trying to do? What the advantage would be to it over what can be done in Objective-C?

mrichmon
Aug 4, 2006, 12:58 PM
In C++, the default behavior is that if you cast a child class to its parent, the parent's methods are called when you call into it.

Doesn't this just mean that you should be explicitly calling super if you want only the parent's methods? An explicit cast to a super-type is effectively the same (from a programmer standpoint) as an explicit call to super. Or am I missing something here?

AlmostThere
Aug 4, 2006, 06:53 PM
If you insist on a static function, use a class function although there is nothing in the sample that makes this appear necessary.

The functions PublicObjAddrToIndex and PublicObjAddrToPvtObj can be implemented with MutableDictionaries.

If you want the actual function that is called through a message, then you should use methodFor:

If you are implementing a Bridge Pattern, then you can do this either with normal inheritance or protocols.

As HiRez says, I don't really see what the problem is...

gekko513
Aug 4, 2006, 09:32 PM
I'm not quite sure if I understand the question or problem, either, but if you're looking for a way to recreate an object from a binary state (serialized, stream, file), take a look at NSCoding and the Introduction to Archives and Serializations Programming Guide for Cocoa (http://developer.apple.com/documentation/Cocoa/Conceptual/Archiving/Archiving.html)

Krevnik
Aug 15, 2006, 09:12 AM
Doesn't this just mean that you should be explicitly calling super if you want only the parent's methods? An explicit cast to a super-type is effectively the same (from a programmer standpoint) as an explicit call to super. Or am I missing something here?

Actually, this would be in the class' implementation. Alternatively, you could simply just not implement the method in the sub-class. The difference between Objective-C and C++ is that if a sub-class over-rides the parent class... there is no clean way to get at the parent's method and ignore the over-ridden method in Objective-C, since each object has its own method table (equivilent to the V-table), and the new method replaces the old one in the table. Even if you do an explicit cast to a super-type, you get the child's behavior.

I abused this quite a bit in an OpenGL engine awhile back for college... :)