IonicWind Software

IWBasic => Object Oriented Programming => Topic started by: Parker on March 04, 2007, 04:11:17 PM

Title: Ctor/dtor not being called
Post by: Parker on March 04, 2007, 04:11:17 PM
I was going to post this as an example, but it keeps crashing. I traced it to the fact that the constructor and destructor are not called. If I use a pointer and new/delete, the destructor is called, but not the constructor.

This code is a conversion of a C++ template class: LinkedList<V>.

autodefine "off"

type p_listnode
pointer _data
pointer _next
pointer prev
end type

class LinkedList
private
pointer head
pointer tail
public
declare LinkedList( )
declare _LinkedList( )

declare add( pointer d ), pointer
declare addHead( pointer d ), pointer
declare insertAfter( pointer node, pointer d ), pointer
declare insertBefore( pointer node, pointer d ), pointer

declare remove( pointer node ), pointer
declare removeAll( )

declare getFirst( ), pointer
declare getLast( ), pointer
declare getNext( pointer node ), pointer
declare getPrev( pointer node ), pointer

declare nodeData( pointer node ), pointer

declare enumerate( uint cb )
declare enumerateBackwards( uint cb )
end class

declare __listcb( pointer d )

sub llfree( pointer _data )
delete _data
end sub

sub LinkedList::LinkedList( )
head = new( p_listnode, 1 )
tail = new( p_listnode, 1 )

*<p_listnode>head._next = tail
*<p_listnode>head._data = 0
*<p_listnode>head.prev = 0

*<p_listnode>tail._next = 0
*<p_listnode>tail._data = 0
*<p_listnode>tail.prev = head
end sub

sub LinkedList::_LinkedList( )
removeAll( )
delete head
delete tail
end sub

sub LinkedList::add( pointer d )
return insertBefore( tail, d )
end sub

sub LinkedList::addHead( pointer d )
return insertAfter( head, d )
end sub

sub LinkedList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode

*<p_listnode>node._data = d

return d
end sub

sub LinkedList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode

*<p_listnode>node._data = d

return d
end sub

sub LinkedList::remove( pointer node )
'' Can't remove head or tail
if *<p_listnode>node._next = 0 or *<p_listnode>node.prev = 0 then return 0

pointer d : d = *<p_listnode>node._data

delete node

*<p_listnode>node.*<p_listnode>_next.prev = *<p_listnode>node.prev
*<p_listnode>node.*<p_listnode>prev._next = *<p_listnode>node._next

return d
end sub

sub LinkedList::removeAll( )
pointer node : node = *<p_listnode>head._next
pointer temp

while node <> tail
temp = *<p_listnode>node._next
delete node
node = temp
wend
end sub

sub LinkedList::getFirst( )
return *<p_listnode>head._next
end sub

sub LinkedList::getLast( )
return *<p_listnode>tail.prev
end sub

sub LinkedList::getNext( pointer node )
pointer nxt : nxt = *<p_listnode>node._next
if nxt <> tail then return nxt

return 0
end sub

sub LinkedList::getPrev( pointer node )
pointer prv : prv = *<p_listnode>node.prev
if prv <> head then return prv

return 0
end sub

sub LinkedList::nodeData( pointer node )
return *<p_listnode>node._data
end sub

sub LinkedList::enumerate( uint cb )
pointer node
node = getFirst( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getNext( node )
wend
end sub

sub LinkedList::enumerateBackwards( uint cb )
pointer node
node = getLast( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getPrev( node )
wend
end sub

''-----
'' Enumeration subroutine

sub listEnumSub( pointer d )
print *<string>d, " ",
end sub

''-----
'' Test program

LinkedList theList

theList.add( "my" )
theList.add( "name" )
theList.add( "is" )
theList.add( "Parker" )
theList.addHead( "Hello," )

theList.enumerate( &listEnumSub )
Title: Re: Ctor/dtor not being called
Post by: Ionic Wind Support Team on March 04, 2007, 04:19:06 PM
LinkedList is already a type, defined in ebstd.incc.  It is part of the built in Emergence linked list functions.

So just rename your class to something else and it works fine.  And I will add an error message ;)
Title: Re: Ctor/dtor not being called
Post by: Ionic Wind Support Team on March 04, 2007, 04:27:36 PM
And you had an error in your coding as well.  In the insertbefore and insertafter methods.  Here are the corrected ones, I renamed the class to PointerList since that is what it is ;)


sub PointerList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode

*<p_listnode>newnode._data = d

return d
end sub

sub PointerList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode

*<p_listnode>newnode._data = d

return d
end sub
Title: Re: Ctor/dtor not being called
Post by: Parker on March 04, 2007, 04:31:12 PM
Okay, I've renamed it "PLinkedList" and it works fine. I also changed two bugs in insertBefore() and insertAfter() where I was changing the data member of the wrong node, so the data would always turn out as null (this error didn't exist in the C++ version, it was an error in translation).

Since this was a template class, it doesn't have an option to delete data members when it removes them. Instead I provided a short subrouine
// callback to free pointer lists
template<class V>
void llfree( V data )
{
delete data;
}


This subroutine also exists in the emergence version. To delete all the data members when you remove them, use this code:
list.enumerate( &llfree )
list.removeAll( )


To delete just one member when you remove it, use this:
pointer d
...
d = list.remove( node )
delete d


This is my working version of it.
autodefine "off"

type p_listnode
pointer _data
pointer _next
pointer prev
end type

class PLinkedList
private
pointer head
pointer tail
public
declare PLinkedList( )
declare _PLinkedList( )

declare add( pointer d ), pointer
declare addHead( pointer d ), pointer
declare insertAfter( pointer node, pointer d ), pointer
declare insertBefore( pointer node, pointer d ), pointer

declare remove( pointer node ), pointer
declare removeAll( )

declare getFirst( ), pointer
declare getLast( ), pointer
declare getNext( pointer node ), pointer
declare getPrev( pointer node ), pointer

declare nodeData( pointer node ), pointer

declare enumerate( uint cb )
declare enumerateBackwards( uint cb )
end class

declare __listcb( pointer d )

sub llfree( pointer _data )
delete _data
end sub

sub PLinkedList::PLinkedList( )
head = new( p_listnode, 1 )
tail = new( p_listnode, 1 )

*<p_listnode>head._next = tail
*<p_listnode>head._data = 0
*<p_listnode>head.prev = 0

*<p_listnode>tail._next = 0
*<p_listnode>tail._data = 0
*<p_listnode>tail.prev = head
end sub

sub PLinkedList::_PLinkedList( )
removeAll( )
delete head
delete tail
end sub

sub PLinkedList::add( pointer d )
return insertBefore( tail, d )
end sub

sub PLinkedList::addHead( pointer d )
return insertAfter( head, d )
end sub

sub PLinkedList::insertAfter( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode.prev = node
*<p_listnode>newnode._next = *<p_listnode>node._next
if *<p_listnode>node._next then *<p_listnode>node.*<p_listnode>_next.prev = newnode
*<p_listnode>node._next = newnode

*<p_listnode>newnode._data = d

return d
end sub

sub PLinkedList::insertBefore( pointer node, pointer d )
pointer newnode : newnode = new( p_listnode, 1 )

*<p_listnode>newnode._next = node
*<p_listnode>newnode.prev = *<p_listnode>node.prev
if *<p_listnode>node.prev <> 0 then *<p_listnode>node.*<p_listnode>prev._next = newnode
*<p_listnode>node.prev = newnode

*<p_listnode>newnode._data = d

return d
end sub

sub PLinkedList::remove( pointer node )
'' Can't remove head or tail
if *<p_listnode>node._next = 0 or *<p_listnode>node.prev = 0 then return 0

pointer d : d = *<p_listnode>node._data

delete node

*<p_listnode>node.*<p_listnode>_next.prev = *<p_listnode>node.prev
*<p_listnode>node.*<p_listnode>prev._next = *<p_listnode>node._next

return d
end sub

sub PLinkedList::removeAll( )
pointer node : node = *<p_listnode>head._next
pointer temp

while node <> tail
temp = *<p_listnode>node._next
delete node
node = temp
wend
end sub

sub PLinkedList::getFirst( )
return *<p_listnode>head._next
end sub

sub PLinkedList::getLast( )
return *<p_listnode>tail.prev
end sub

sub PLinkedList::getNext( pointer node )
pointer nxt : nxt = *<p_listnode>node._next
if nxt <> tail then return nxt

return 0
end sub

sub PLinkedList::getPrev( pointer node )
pointer prv : prv = *<p_listnode>node.prev
if prv <> head then return prv

return 0
end sub

sub PLinkedList::nodeData( pointer node )
return *<p_listnode>node._data
end sub

sub PLinkedList::enumerate( uint cb )
pointer node
node = getFirst( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getNext( node )
wend
end sub

sub PLinkedList::enumerateBackwards( uint cb )
pointer node
node = getLast( )
while node <> 0
!<__listcb>cb( *<p_listnode>node._data )
node = getPrev( node )
wend
end sub

''-----
'' Enumeration subroutine

sub listEnumSub( pointer d )
print *<string>d, " ",
end sub

''-----
'' Test program

PLinkedList theList

theList.add( "my" )
theList.add( "name" )
theList.add( "is" )
theList.add( "Parker" )
theList.addHead( "Hello," )

theList.enumerate( &listEnumSub )

do:until inkey$<>""


Edit - I found that out a few minutes ago too. It was a translation error - going through code quickly I didn't see the difference between node and newnode.