Function Pointer

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Ana

Betreff: Function Pointer

BeitragMi, Okt 24, 2012 12:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich hab einen Menueintrag, von dem ich möchte, dass er eine Function ausführt wenn man ihn anklickt, diese Funktion soll aber nicht fest, sondern variabel bleiben. Dazu hat der Type ein Field Action() dem dann eine Funktion zugewiesen wird. Das funktioniert auch soweit wenn es eine bestimmte funktion ist. Wenn ich aber nun möchte das der Name des Menueintrags- Objektes, das angeklickt wurde ausgegeben wird und ich der Funktion nicht den Eintrag als Parameter übergeben will, wie komme ich dadran? Als Methode wäre das natürlich einfach aber die lassen sich nicht übergeben oder?

Danke schon mal,

Ana
Don't only practice your art,
but force your way into its secrets,
for it and knowledge
can raise human to divine

kog

BeitragMi, Okt 24, 2012 12:40
Antworten mit Zitat
Benutzer-Profile anzeigen
und wenn du die Menüs als Type machst mit Vererbung der Hauptklasse für Menüs?

Code: [AUSKLAPPEN]
Type TMenu
field name:String
  method Action() abstract
  end type

type TTestMenu extends TMenu
  method action()
     print("Hallo")
     print(self.name)
  end method
end type


global TestMenu:TTestMenu=new TTestMenu


if Mousehit(1) TestMenu.Action()


Dadurch kannst du die Aciton() Method immer aufrufen, egal obs jetzt vom TMenu Objekt ist oder du das Objekt direkt hast.
Windows 7 Home Premium 64bit
CPU: Intel Core i5 3450 Ivy Bridge
GPU: HIS HD 4870 1GB GDDR5
RAM: 4x 4GB DDR3-SDRAM Dual Channel
 

PhillipK

BeitragMi, Okt 24, 2012 12:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Ob sich Methoden übergeben lassen, weiß ich nicht genau. Eventuell über einen umweg, aber direkt pointern ist, soweit ich mich erinnere, nicht.

Ich habe das ganze immer über ein Dummy gelöst:
BlitzMax: [AUSKLAPPEN]

'Masterklasse, um parameter zu übergeben -> Functionpointer
Type TParamDummy
End Type
'Ein beispiel "parameter"
Type TParam_image Extends Dummy
Field img:TImage
Function CreateImgParam:TParamDummy(img:TImage)
Local idum:TParam_image = New TParam_image
idum.img = img
Return idum
End Function
End Type

Local testfunc(obj:TParamDummy)
Local param1:TParamdummy = TParam_image.createimgparam(irgendein_image)

Function test1(pbj:TParamDummy)
Local idum:TParam_image = TParam_image(obj)
If idum Then
DrawImage(5,5, idum.img)
EndIf
End Function

testfunc = test1

testfunc(param1)



So, im groben etwa.
Grade bei menüeinträgen hat mich die starke einschränkung im bezug auf functionpointer immer aufgeregt. Deshalb nutze ich nun immer ein einzelnes object oder dummytype als parameter. Object caste ich zu *beliebig* bzw nutze halt eine, wie oben grob aufgeschriebene, dummyklasse.
Wichtig ist halt immer, das du WEISST was für typen es sein könnten. So kannst du in einem If/Elseif block abfragen, welche klasse grade als funktion reinkam.

Vielleicht hilft dir das ja beim weiteren überlegen Smile

Ps:

Spezifischer auf dein problem bezogen:
Soweit mir bekannt, kann man nicht feststellen, woher eine funktion kommt, bzw wo sie aufgerufen wurde. Maximal über eine globale variable.

Allerdings denke ich, das du eben wegen der einschränkung bezüglich der parameter eben nichts übergeben möchtest (Overriding function differs by type ? oder so ähnlich) - hier hilft der ansatz, object oder dummytype zu verwenden. Bedarf anfangs etwas gewöhnung, eventuell auch etwas umschreiben deines Codes, aber hinterher hast du voll dynamische funktionen, wo lediglich das erstellen der parameter nervt. Smile



------
Nachtrag:

@Kog:

Soweit ich verstanden habe, hat sie ein _FIELD_ Action() -> Functionspointer.
Es kann in einem menu durchaus vorkommen, das man mehrere unterschiedliche funktionen aufrufen möchte, bzw eventuell wirds auch ein gui framework, wo der user hinterher selber seine funktionen einbauen soll.
Wie dem auch sei. Ana: Solltest du wirklich Functionspointer -BRAUCHEN-, ist etwas in meine richtung zu empfehlen.
Schreibst du allerdings eh das Gui spiele bezogen, sprich jeder menüpunkt wird ein eigenes type um volle funktionalität einzubauen oder sonstwie käse.. Sprich: Du weißt vorher schon, das die funktionen fest sind, dann solltest du Kog's weg nutzen. Einfacher, übersichtlicher, mächtiger. Smile

kog

BeitragMi, Okt 24, 2012 12:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Und wenn man mit ähnlichem Verfahren wie TEvent arbeiten würde? und eine die Funktion nach dem Schema aufgebaut sein muss:
Code: [AUSKLAPPEN]
Function Test123:Irgendwas(event:TEvent)
   local men:TMenu=TMenu(event.extra) 'oder source
   print men.name
end Function

type TMenu
field name:String
 field _action:Irgendwas(event:TEvent)
method Setaction(func:Irgendwas(event:TEvent))
  self._action(func)
end method

method Click()
  local event:TEvent=new TEvent
event.extra=self
event.id=CLICK
self._action(event)
end method
end type

local menu:TMenu=new TMenu
menu.name="Ein test"
Menu.SetAction(Test123)

menu.Click()


Wäre das was eher? oder habe ich die Frage komplett falsch verstanden?

*Achtung, Code aus dem Kopf, sollte nur ein Denkanstoss sein*
Windows 7 Home Premium 64bit
CPU: Intel Core i5 3450 Ivy Bridge
GPU: HIS HD 4870 1GB GDDR5
RAM: 4x 4GB DDR3-SDRAM Dual Channel

BladeRunner

Moderator

BeitragMi, Okt 24, 2012 14:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein Method-Pointer wäre btw. nur ein Functionpointer der als Parameter die Instanz mit übergibt, von daher kannst Du es eigentlich auch so machen Wink (Intern sind Methoden auch Funktionen mit 'verstecktem' erstem Parameter)
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

Hangman

BeitragMi, Okt 24, 2012 22:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Strategy Pattern
Programmiere gegen eine Schnittstelle, nicht gegen eine Implementierung.
Somit würde ich mich kog's erstem Vorschlag anschließen und diesen Ansatz empfehlen.

BlitzMax: [AUSKLAPPEN]

Type myInterface Abstract
Method action() Abstract
End Type

Type myImpl1 Extends myInterface
Method action()
'muss erzwungenermaßen implementiert werden
End Method
End Type

Type myImpl2 Extends myInterface
Method action()
'muss erzwungenermaßen implementiert werden
End Method
End Type

Type Main
Function start()
Local myImpl:myInterface = New myImpl1 oder New myImpl2
myImpl.action()
End Function
End Type

So kann man jede Klasse einsetzen, die das Interface implementiert.
Ich habe Berthold gebrochen.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group