Function pointer wont compile

BlitzMax Forums/BlitzMax Programming/Function pointer wont compile

ImaginaryHuman(Posted 2007) [#1]
I'm having some difficulty with function pointers, and quite possibly this might be a limitation of BlitzMax as a language/compiler.

I have an array of Objects in which I will be storing custom types of various kinds. Obviously this means that once the objects are in the array, you do not know what type of object they really are.

I have an array of Kinds, which is just an integer value referring to what kind of object it originally was.

The simple (but inefficient) solution for getting the right type of object out of the array is to do a Select-Case based on the Kind[Offset] for Objects[Offset].
This of course works. Also *if I know* the situation in which a given object type is to be used, such as that I need a TPixmap object, I can of course just cast it like TPixmap(Objects[Offset]). Becauase I am explicitly casting it within the sourcecode, the compiler knows that I can then call any functions or methods within TPixmap and it will be valid, e.g. TPixmap(Objects[Offset]).ReadPixel(10,5). Because the compiler knows the allowed methods of TPixmap objects, and knows I am casting it to a TPixmap, it lets it be compiled.

On the other hand, there are situations where I do not know the type of object and want to just, for example, go through all the objects stored and call a method that they all share. For example each of my custom types has a PrintSelf() method that prints details about its fields. I want to be able to run through the objects array, *not* using the kinds array, and call the PrintSelf() method of each object. To do this, what I am trying to do is have a Function Pointer for each object. This function pointer points to a Convert() function within the custom type. So all I should have to do is go through the objects and call, for example, ConversionFunctions[Offset](Objects[Offset]).PrintSelf()

However, the compiler will not compile the sourcecode. It says the PrintSelf() is not defined. I think that this is because it doesn't know what type of object it is dealing with and so is either looking in the Object() type and not finding that method, or it knows that it just can't tell what the type will be so it can't verify that it's a valid method. Is that what's happening?

Is there some way I can call the ConversionFunction (which would simply =Convert() function within a given type, to which you pass an object), and get it to convert to a specific object type, and then also call the method within that type, and have the compiler say it's ok?

I am wondering if it's because the array of Conversion Functions is defined as Converters:Object(Obj:Object)[], which means that no matter what type is returned from Convert() it will change it into just an Object and so won't return the actual type of object? How could I store the functions in one array even though they each return different types?

e.g. A Convert() function might look like:
[code]
Function Convert:MyType(Obj:Object)
Return MyType(Obj)
End Function
[Code]

Am I right in thinking that storing this in an array of function pointers that return Objects, cancells out the type conversion?

How can I make this work, so I can call Converters[Offset](Objects[Offset]).PrintSelf()
???


Gabriel(Posted 2007) [#2]
You could create a base type which has abstract methods for all the shared methods, have all the other types extend that type, and then make the array an array of your basetype instead of an array of objects.


ImaginaryHuman(Posted 2007) [#3]
That's a good idea, except that it means I can only store custom types. I wouldn't be able to also store, for example, a TPixmap. Right?

Also there are no shared methods as such, each custom type would have different code for PrintSelf(), for example.

What is an abstract method?


H&K(Posted 2007) [#4]
I dissagree with Gabs "Could"
If all your objects have a printself(), then that should really be a member of the base class.
The rest of what he said I agree with, extend Object (which is like the norm), with abstract mehtods of all the things that you want in all your dirived types, then extend the current base types from MyObject.

I know this is just opinion, but in mine (opinion), it shows a lack of planning not to have the common methods/fields in the base type. (Im not having a go, just saying that when I run into problems like this, its normaly becase of lack of planning on my part)

Edit, just read your post. Would TPixmap have a Printself?
An abstract method is one you declare, but dont define.
Abstract and Final
User defined types and methods can also be declared abstract or final by adding Abstract or Final to the appropriate declaration:

Type AbstractType Abstract
Method AbstractMethod() Abstract
End Type

Type FinalType Final
Method FinalMethod() Final
Print "FinalType.FinalMethod"
End Method
End Type

Declaring a user defined type abstract means that you can not create instances of it using New. However, it is still possible to extend such types and create instances of these derived types. Declaring a method abstract means that the method has no implementation and must be implemented by a derived type. Any user defined type with at least one abstract method is itself abstract.

Declaring a user defined type final means that it can not be extended. Declaring a method final means that derived types can not override the method. All methods of a final user defined type are themselves final.

Abstract types and methods are mostly used to create 'template' types and methods that leave implementation details up to derived types.

Final types and methods are mostly used to prevent modification to a type's behaviour.



Gabriel(Posted 2007) [#5]
Also there are no shared methods as such, each custom type would have different code for PrintSelf(), for example.

As long as they have the some number and type of parameters, that'll be fine. As H&K's description explains, it's really just a template. It's saying all objects will be able to do this, but they'll all do it differently.

With regard to storing a TPixmap, no you wouldn't. In that instance, you would have to store objects in the list, and then cast the object to your basetype before you call printself on it. So instead of casting to a type, you'd be casting to a group of types.


ImaginaryHuman(Posted 2007) [#6]
Wowza. Well, it does indeed work. Thanks guys!

I set up an abastract base type with the methods and functions that would be the same name in each type (and yes they have the same parameters), also as abstract. Then I made the custom types extended from the base type, and Final. I noticed in the documentation about custom types, under language, that it says to just put Final to make a type final, but it doesn't say to put the Extends AND the Final together on the same line. ie

Type MyType Extends BaseType Final

So the documentation is a bit unclear. It makes it seem like you just put Final and don't need to define what it extends from.

But anyway, I did this and implemented the conversion functions array, which is an array of BaseType. I have the Convert() function returning a specific type which derives from the base type. Then to my delight I find that I can simply do:

Objects[Count].PrintFull()

and it will actually recognize that it's a legal function, and will call it, regardless of whether it looks like it would know what custom type it is inside of. Very cool! THEN I realized I don't even need the conversion functions (or array of them) at all, really. I don't have to initially convert the type and then call PrintFull(). But for now I think I will leave those in there in case I need them later.

Thanks again.