Procedure vorhanden?
Re: Procedure vorhanden?
Nun, eine BaseClass könnte zB Methoden haben, die nicht verändert werden dürfen, in der Regel als <Static> markierte( Static ist ein KeyWord in PB, deshalb bei mir <Definitiv>)
Dann könnte es nötig sein eine Bestimmte Function zu haben, zB weil eine andere Function Darauf zugreift, aber jetzt noch nicht implementiert werden kann, sondern von den ChildClass geliefert wird, in der BaseClass aber definiert, diese sind <Abstract>.
Dann sind noch Functionen, die überschriben werden können, diese sind <Virtuell> karkiert.
Das soll in der BaseClass gemacht werden und ist eigendlich ein Eintrag in einer Map (via Macro)
Diese Maps sind Public und können mit zB BaseClass::Abstract(. . .). . . eingesehen werden und . . .
Ok, soweit bin ich schon. Ziel ist es, zB ein überschreiben einer <Definitiv>Function zu verhindern(Error), ein überschreiben einer <Acstract)Function zu "fordern" sonst(Error)
und sicherzustellen, dass <Virtuell> selbstständig überschrieben wird.
Ich gehe davon aus, dass derjenige, der eine ChildClass schreibt weiss, welche Functionen in der BaseClass sind und auch Ihren Status kennt.
Das heisst, zu überschreibende Functionen dürfen nicht im Interface erscheinen, Sie sind ja schon in der BaseClass und dürfen in der ChildClass nur implementiert werden.
Zu <Virtuel>, hier sind nicht nur die Functionen der BaseClass zu markieren, sondern auch in der ChildClass,(Soll sie überschrieben werden?, oder ist sie zwar implementiert, aber in diesem Fall nicht benötigt)
Ich denke, dass es Situationen gibt, in denen die Base-Function gebraucht wird und Situationen, in denen diese Function überschrieben werden soll.
An diesem Punkt bin ich gerade
Ach ja, Überladen kann mann auch simulieren, gell!
Code dazu kommt später, muss erst mal zum TÜV . . .
Dann könnte es nötig sein eine Bestimmte Function zu haben, zB weil eine andere Function Darauf zugreift, aber jetzt noch nicht implementiert werden kann, sondern von den ChildClass geliefert wird, in der BaseClass aber definiert, diese sind <Abstract>.
Dann sind noch Functionen, die überschriben werden können, diese sind <Virtuell> karkiert.
Das soll in der BaseClass gemacht werden und ist eigendlich ein Eintrag in einer Map (via Macro)
Diese Maps sind Public und können mit zB BaseClass::Abstract(. . .). . . eingesehen werden und . . .
Ok, soweit bin ich schon. Ziel ist es, zB ein überschreiben einer <Definitiv>Function zu verhindern(Error), ein überschreiben einer <Acstract)Function zu "fordern" sonst(Error)
und sicherzustellen, dass <Virtuell> selbstständig überschrieben wird.
Ich gehe davon aus, dass derjenige, der eine ChildClass schreibt weiss, welche Functionen in der BaseClass sind und auch Ihren Status kennt.
Das heisst, zu überschreibende Functionen dürfen nicht im Interface erscheinen, Sie sind ja schon in der BaseClass und dürfen in der ChildClass nur implementiert werden.
Zu <Virtuel>, hier sind nicht nur die Functionen der BaseClass zu markieren, sondern auch in der ChildClass,(Soll sie überschrieben werden?, oder ist sie zwar implementiert, aber in diesem Fall nicht benötigt)
Ich denke, dass es Situationen gibt, in denen die Base-Function gebraucht wird und Situationen, in denen diese Function überschrieben werden soll.
An diesem Punkt bin ich gerade
Ach ja, Überladen kann mann auch simulieren, gell!
Code dazu kommt später, muss erst mal zum TÜV . . .
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
Ich hab jetzt mal einen DemoCode erstellt.
Vereerbung funktioniert, überschreiben auch!
OOP:: enthält die Methoden von IUnknown
Parent:: implementiert dann IUnknown und erweitert es
Child: implementiert IParent und erweitert es. In Child wird dann eine eigene MethodeA() erstellt, welche Parent\MethodeA() überschreibt
Die VTable wurde mit einem Public Array realisiert, damit man die Methodenadressen einfach in die abgeleitete Klasse kopieren kann!
Vereerbung funktioniert, überschreiben auch!
OOP:: enthält die Methoden von IUnknown
Parent:: implementiert dann IUnknown und erweitert es
Child: implementiert IParent und erweitert es. In Child wird dann eine eigene MethodeA() erstellt, welche Parent\MethodeA() überschreibt
Die VTable wurde mit einem Public Array realisiert, damit man die Methodenadressen einfach in die abgeleitete Klasse kopieren kann!
Code: Alles auswählen
; update: missing Pointer *This fixed
; update: added Macro Implement_VTable
; update: VTable Definition As Byte
DeclareModule OOP
; IUnknown ist in PB bereits definiert
; Interface IUnknown
; ; IUnknown
; QueryInterface(*riid, *addr)
; AddRef()
; Release()
; EndInterface
Structure TThis
; iUnknown
*vTable ; Pointer to VirtalMethodeTable (Addresslist of Methodes declared in the Interface)
cntRef.i ; Object reference counter
objMutex.i ; Object Mutex! Only if object used by different treads! It shows that Object is in operation by a thread!
EndStructure
Global Dim VTable.a(SizeOf(IUnknown)-1)
Macro IUnknownToVTable
CopyMemory(OOP::@VTable(), @VTable(), SizeOf(IUnknown))
EndMacro
Macro InterfaceToVTable(ModuleName, InterfaceName)
CopyMemory(ModuleName::@VTable(), @VTable(), SizeOf(ModuleName::InterfaceName))
EndMacro
EndDeclareModule
Module OOP
EnableExplicit
; ======================================================================
; Implement the Methodes of iUnknown
; ======================================================================
; QueryInterface : part of iUnknown, for PureBasic only it's not needed
Procedure QueryInterface(*This.TThis, *riid, *addr)
ProcedureReturn $80004002 ; (#E_NOINTERFACE)
EndProcedure
Procedure AddRef(*This.TThis)
; ======================================================================
; Increment the ReferenceCounter! This is used if you do Multithreading
; and access 1 ObjectInstance from 2 different Threads
; in VB6/VBA we can't to this because it is single threading only!
; in PureBasic we can use Multitherading with language integrated
; command CreateThread()
; ======================================================================
If *This
LockMutex(*This\objMutex)
*This\cntRef + 1
UnlockMutex(*This\objMutex)
ProcedureReturn *This\cntRef
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure Release(*This.TThis)
; ======================================================================
; Decrement the ReferenceCounter! Destroy the object?
; If we do Multithreading and the object is referenced by more than 1
; Thread, only the reference counter will be decremented.
; If it is the last reference to the object it will be destroyed.
; This is the normal way for single threaded programms were we have
; only 1 reference!
; ======================================================================
If *This
With *This
LockMutex(\objMutex)
If \cntRef = 1 ; If it is the last reference THEN delete the object
;
; Maybe further operations here for cleanup
; ---
; Dispose(*this)
; ---
FreeMutex(\objMutex) ; Delete the Mutes
FreeStructure(*This) ; Relase the allocated memory; kill the instance
ProcedureReturn 0
Else
\cntRef - 1 ; Decrement No of referenced threads
EndIf
UnlockMutex(\objMutex)
EndIf
ProcedureReturn \cntRef
EndWith
EndProcedure
; Write Methodes Address into VTable
PokeI(@VTable() + OffsetOf(IUnknown\QueryInterface()), @QueryInterface() )
PokeI(@VTable() + OffsetOf(IUnknown\AddRef()), @AddRef() )
PokeI(@VTable() + OffsetOf(IUnknown\Release()), @Release() )
Debug "VTable Adress of IUnknown"
Debug @VTable()
Debug @VTable(0)
EndModule
; ********************************************************************************
DeclareModule Parent
Interface IParent Extends IUnknown
MethodeA(a1.i)
MethodeB(b1.i)
EndInterface
Structure TThis Extends OOP::TThis ; This is the Structure for the Class Instance Data
mName.s
EndStructure
Global Dim VTable.a(SizeOf(IParent)-1)
Macro Implement_VTable
;CopyMemory(Parent::@VTable(), @VTable(), SizeOf(Parent::IParent))
OOP::InterfaceToVTable(Parent, IParent)
EndMacro
Declare.i New() ; Public Procedure to create new instance
EndDeclareModule
; ----------------------------------------------------------------
Module Parent
EnableExplicit
; Anzahl der Einträge in der VTable
; Debug "SizeOfInteface " + Str(SizeOf(IParent)/SizeOf(Integer))
Procedure MethodeA(*This.TThis, a1.i)
Debug "Parent MethodeA a1= " + Str(a1)
EndProcedure
Procedure MethodeB(*This.TThis, b1.i)
Debug "Parent MethodeB b1 = " + Str(b1)
EndProcedure
Procedure New()
; ======================================================================
; Creates a New Instance of the ClassObject
; it Returns the Pointer to the allocated memory or
; 0 if it couldn't get the memory from OS
; ======================================================================
Protected *obj.TThis
; Schritt 1: Speicher anfordern. Dazu bietet sich AllocateStructure an, weil diese auch den Speicher initialsiert
*obj = AllocateStructure(TThis)
; Schritt 2: Erforderlich Zeiger setzen und Mutex anlegen. Aber nur wenn Speicher vorhanden ist (Out Of Memory ?)
If *obj
*obj\vTable = @VTable(0) ; Zeiger auf die Funktionstabelle setzen (Methoden). Siehe weiter unten.
*obj\objMutex = CreateMutex() ; Mutex zum Schutz des RefCounter anlegen, kann auch in den Funktionen verwendet werden
; Zum Beipiel wenn auf das Objekt aus verschiedenen Threads zugegriffen wird
*obj\cntRef = 1
; Eventuelle weitere Zuweisungen. Zum Beipiel eine New-Funktion mit Parametern
EndIf
ProcedureReturn *obj
EndProcedure
; Implement IUnknown
;CopyMemory(OOP::@VTable(), @VTable(), SizeOf(IUnknown))
OOP::IUnknownToVTable
; Write Methodes Address into VTable
PokeI(@VTable() + OffsetOf(IParent\MethodeA()), @MethodeA() )
PokeI(@VTable() + OffsetOf(IParent\MethodeB()), @MethodeB())
EndModule
; ********************************************************************************
DeclareModule Child
Interface IChild Extends Parent::IParent
MethodeC(c1.i)
EndInterface
Structure TThis Extends Parent::TThis ; This is the Structure for the Class Instance Data
; MyClassData
EndStructure
Global Dim VTable.a(SizeOf(IChild)-1)
Macro Implement_VTable
;CopyMemory(IChild::@VTable(), @VTable(), SizeOf(Child::IChild))
OOP::InterfaceToVTable(Child, IChild)
EndMacro
Declare.i New() ; Public Procedure to create new instance
EndDeclareModule
Module Child
EnableExplicit
; ======================================================================
; Implements the Methodes of iUnknown
; ======================================================================
; Implement a new MethodeA for Child => tp overwrite Parent\MethodeA
Procedure MethodeA(*This.TThis, a1.i)
Debug "Child MethodeA a1= " + Str(a1)
EndProcedure
Procedure MethodeC(*This.TThis, c1.i)
Debug "Child MethodeC c1 = " + c1
EndProcedure
Procedure New()
; ======================================================================
; Creates a New Instance of the ClassObject
; it Returns the Pointer to the allocated memory or
; 0 if it couldn't get the memory from OS
; ======================================================================
Protected *obj.TThis
; Schritt 1: Speicher anfordern. Dazu bietet sich AllocateStructure an, weil diese auch den Speicher initialsiert
*obj = AllocateStructure(TThis)
; Schritt 2: Erforderlich Zeiger setzen und Mutex anlegen. Aber nur wenn Speicher vorhanden ist (Out Of Memory ?)
If *obj
*obj\vTable = @VTable() ; Zeiger auf die Funktionstabelle setzen (Methoden). Siehe weiter unten.
*obj\objMutex = CreateMutex() ; Mutex zum Schutz des RefCounter anlegen, kann auch in den Funktionen verwendet werden
; Zum Beipiel wenn auf das Objekt aus verschiedenen Threads zugegriffen wird
*obj\cntRef = 1
; Eventuelle weitere Zuweisungen. Zum Beipiel eine New-Funktion mit Parametern
EndIf
ProcedureReturn *obj
EndProcedure
; Implement IParent
;CopyMemory(Parent::@VTable(), @VTable(), SizeOf(Parent::IParent))
Parent::Implement_VTable
; Write Methodes Address into VTable
PokeI(@VTable() + OffsetOf(IChild\MethodeC()), @MethodeC() )
; Overwrite Parent\MethodA with Cild\MethodeA
PokeI(@VTable() + OffsetOf(IChild\MethodeA()), @MethodeA() )
EndModule
; Testcode
Global *MyParent.Parent::IParent ; Object of BaseClass
Global *MyChild.Child::IChild
*MyParent = Parent::New()
*MyChild = Child::New()
Debug #Null$
Debug "Call Parent Methodes"
*MyParent\MethodeA(1)
*MyParent\MethodeB(2)
Debug #Null$
Debug "Call Child Methodes"
*MyChild\MethodeA(3) ; here Child\MethodeA is called because of overwrite
*MyChild\MethodeB(4) ; here Parent\MethobeB is called (not overwritten)
*MyChild\MethodeC(5)
Zuletzt geändert von SMaag am 04.08.2023 16:50, insgesamt 2-mal geändert.
Re: Procedure vorhanden?
Die Bezeichnung Parent und Client für Vererbung ist hier nicht passend und hat eine andere Bedeutung in der OOP Programmierung.
Es ist besser hier über Basis Klasse und Sub Klasse zu sprechen ...
Siehe Beschreibung: viewtopic.php?t=29343
Parent und Client:
Ein Parent ist ein eigenes Objekt und ein Client ist eigenes Objekt mit einen verweis auf das Parent Objekt.
ein Client Objekt kann auch wieder ein Client Objekt haben, wobei der Parent Verweis auf das vorherige Client Objekt ist.
Dieses in PB zu erstellen ist möglich, aber sehr aufwendig.
Es ist besser hier über Basis Klasse und Sub Klasse zu sprechen ...
Siehe Beschreibung: viewtopic.php?t=29343
Parent und Client:
Ein Parent ist ein eigenes Objekt und ein Client ist eigenes Objekt mit einen verweis auf das Parent Objekt.
ein Client Objekt kann auch wieder ein Client Objekt haben, wobei der Parent Verweis auf das vorherige Client Objekt ist.
Dieses in PB zu erstellen ist möglich, aber sehr aufwendig.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Procedure vorhanden?
Code: Alles auswählen
Die Bezeichnung Parent und Client für Vererbung ist hier nicht passend und hat eine andere Bedeutung in der OOP Programmierung.
Es ist besser hier über Basis Klasse und Sub Klasse zu sprechen ...
Ich hatte leider auch nicht bemerkt, dass es im englischen Forum bereits einen größeren Beitrag mit Code dazu gibt, der bereits funktioniert!
Damit ist die Diskussion eigentlich hinfällig. Ich dachte es geht noch um die Grundlagen, das hinzubekommen.
Hab mir das angesehen:
so ist das natürlich schon recht komfortabel und durch die die Makros wie AsMethode() usw. wird die Fehlernafälligkeit beim hantieren
mit den VTable Pointer praktisch ausgeschlossen. Leider recht dürftig dokumentiert und durch die vielen Makros und Verschachtelung nur schwer durchschaubar!
Zuletzt geändert von SMaag am 04.08.2023 19:27, insgesamt 1-mal geändert.
Re: Procedure vorhanden?
Da ist eine neue Frage aufgetaucht:
Was ist dieses IUnknown-Interface?
Ich habe darüber keine Infos finde können.
Was ist dieses IUnknown-Interface?
Ich habe darüber keine Infos finde können.
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
MSDN:Olafmagne hat geschrieben: 04.08.2023 18:12 Da ist eine neue Frage aufgetaucht:
Was ist dieses IUnknown-Interface?
Ich habe darüber keine Infos finde können.
https://learn.microsoft.com/de-de/windo ... nheritance
https://learn.microsoft.com/de-de/windo ... n-iunknown
WIKI:
https://de.wikipedia.org/wiki/Component_Object_Model
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Procedure vorhanden?
nochmal zum Code von BaseClass aus dem englischen Forum.
wie schon gesagt im Detail schwierig zu kapieren!
dazu einige Fragen
Structure udtClass
Array *vTable(3)
Array Initialize.udtInvoke(0)
Array Dispose.udtInvoke(0)
*Package.sPackage
EndStructure
1. was für eine Struktur ist sPackage, ist wieder nirgends zu finden, auch nicht im StructurViewer!
Muss wieder was in PB implementiert sein, da es keinen Fehler gibt! Komischer Weise kann man
sPackage nur innerhalb einer Structure verwenden sonst gibt es Fehler
2. Warum ist Initialize und Dispose ein Array
Je Klasse gibt es doch eigentlich nur eine Methode für Initialize und Dispose
Welchen Sinn macht es mehrere zu haben?
wie schon gesagt im Detail schwierig zu kapieren!
dazu einige Fragen
Structure udtClass
Array *vTable(3)
Array Initialize.udtInvoke(0)
Array Dispose.udtInvoke(0)
*Package.sPackage
EndStructure
1. was für eine Struktur ist sPackage, ist wieder nirgends zu finden, auch nicht im StructurViewer!
Muss wieder was in PB implementiert sein, da es keinen Fehler gibt! Komischer Weise kann man
sPackage nur innerhalb einer Structure verwenden sonst gibt es Fehler
2. Warum ist Initialize und Dispose ein Array
Je Klasse gibt es doch eigentlich nur eine Methode für Initialize und Dispose
Welchen Sinn macht es mehrere zu haben?
Re: Procedure vorhanden?
@mk-soft
OK, IUnknown ist reiner Windowskram.
Dann sollte ich das nicht brauchen, da ich meine eigenen Klassen schreiben möchte und möglichst unabhängig von einem bestimmten System (auch wenn das ein oder andere sinnvoll ist, wenn es auf allen OS Ähnliches gibt) sein möchte.
OK, IUnknown ist reiner Windowskram.
Dann sollte ich das nicht brauchen, da ich meine eigenen Klassen schreiben möchte und möglichst unabhängig von einem bestimmten System (auch wenn das ein oder andere sinnvoll ist, wenn es auf allen OS Ähnliches gibt) sein möchte.
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
Zu 1.SMaag hat geschrieben: 04.08.2023 19:35 nochmal zum Code von BaseClass aus dem englischen Forum.
wie schon gesagt im Detail schwierig zu kapieren!
dazu einige Fragen
Structure udtClass
Array *vTable(3)
Array Initialize.udtInvoke(0)
Array Dispose.udtInvoke(0)
*Package.sPackage
EndStructure
1. was für eine Struktur ist sPackage, ist wieder nirgends zu finden, auch nicht im StructurViewer!
Muss wieder was in PB implementiert sein, da es keinen Fehler gibt! Komischer Weise kann man
sPackage nur innerhalb einer Structure verwenden sonst gibt es Fehler
2. Warum ist Initialize und Dispose ein Array
Je Klasse gibt es doch eigentlich nur eine Methode für Initialize und Dispose
Welchen Sinn macht es mehrere zu haben?
Package ist ein Zeiger auf Globale Daten die über alle Objekte von der Klasse gemeinsam sind. Hier kann man zum Beispiel ein Objekt Zähler hinterlegen.
Den Inhalt des Daten Struktur 'sPackage' legt man selber fest. Wenn es diese nicht gibt ignoriert PB diese Struktur.
Beispiel 4: https://www.purebasic.fr/english/viewto ... 92#p555092
Zu 2.
Eine Mehrfachvererbung ist ja möglich. Somit kann auch die Klasse eine Initialize und Dispose besitzen die mit Vererbt wird und auch aufgerufen werden muss.
Bei der ersten Klasse erbt man die BaseClass und legt die Methoden und die Initialize, Dispose an.
Jetzt kann diese Klasse wieder vererbt werden und die erweiterten Methoden und die zusätzliche Initialize, Dispose hinzufügen.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Procedure vorhanden?
Das stimmt, aber die Methoden AddRef und Release werden auch jedem fall benötigt. Da kann man auch gleich die QuerInterface mitliefernOlafmagne hat geschrieben: 04.08.2023 20:25 @mk-soft
OK, IUnknown ist reiner Windowskram.
Dann sollte ich das nicht brauchen, da ich meine eigenen Klassen schreiben möchte und möglichst unabhängig von einem bestimmten System (auch wenn das ein oder andere sinnvoll ist, wenn es auf allen OS Ähnliches gibt) sein möchte.
(Was ich auch mal bei Windows benötigte)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive