Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2004-07

Linked List/ pointers/ casting/ OOP Question

13 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ron Weidner

I thought I was getting closer to understanding
pointers but it appears that I'm still not getting it. I wrote the following code fragment but it doesn't compile. the errors I get are...

Widget_container_class.pas(80,27) Error: Illegal
qualifier
Widget_container_class.pas(88,23) Error: Illegal
qualifier
Widget_container_class.pas(88,29) Error: Illegal
expression
Widget_container_class.pas(88,29) Fatal: Syntax error,
";" expected but "(" found

I numbered lines 80 and 88 in comments so that the error messages make sense. (to the experienced
programmer like yourself :) )Please let me know if you see what the problems are.

{$H+}
unit Widget_container_class;
interface
uses
Attribute_class,Widget_class,Widget_entity_class,web;
type PWidgetList=^TWidgetList;
TWidgetList=record
	widget:pointer;
	next:PWidgetList;
end;
type PWidgetContainer=^TWidgetContainer;
TWidgetContainer=Object(TWidget)
	private
		PCurWidget,PHeadWidget:PWidgetList;
		text:string;
	public
		constructor init(ATag:string);
		procedure Render();
		procedure SetText(str:string);
		function GetText():string;
		procedure MoveFirstWidget();
		procedure MoveLastWidget();
		procedure AddWidget(PWidget:pointer);
		procedure RenderWidgets();
end;
procedure TWidgetContainer.RenderWidgets();
begin
	MoveFirstWidget();
	while (PCurWidget^.next  nil) do
	begin
		PCurWidget^.widget:=PWidget(PCurWidget^.widget); //
cast the pointer to a widget pointer
		if (PCurWidget^.widget^.meta = 'ENTITY') then //
this is line 80
		begin
PCurWidget^.widget:=PWidgetEntity(PCurWidget^.widget);
		end
		else
		begin
PCurWidget^.widget:=PWidgetContainer(PCurWidget^.widget);
		end;
		PCurWidget^.widget^.Render(); //line 88
		PCurWidget:=PCurWidget^.next;
		dispose(PHeadWidget);
		PHeadWidget:=PCurWidget;
	end;
end;

Ron_W

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail

Reply by email

Unknown author
to Ron Weidner
Ron Weidner wrote 53 lines
I thought I was getting closer to understanding pointers but it appears that I'm still not getting it. I wrote the following code fragment but it doesn't compile. the errors I get are... Widget_container_class.pas(80,27) Error: Illegal qualifier Widget_container_class.pas(88,23) Error: Illegal qualifier Widget_container_class.pas(88,29) Error: Illegal expression Widget_container_class.pas(88,29) Fatal: Syntax error, ";" expected but "(" found I numbered lines 80 and 88 in comments so that the error messages make sense. (to the experienced programmer like yourself :) )Please let me know if you see what the problems are. {$H+} unit Widget_container_class; interface uses Attribute_class,Widget_class,Widget_entity_class,web; type PWidgetList=^TWidgetList; TWidgetList=record widget:pointer; next:PWidgetList; end; type PWidgetContainer=^TWidgetContainer; TWidgetContainer=Object(TWidget) private PCurWidget,PHeadWidget:PWidgetList; text:string; public constructor init(ATag:string); procedure Render(); procedure SetText(str:string); function GetText():string; procedure MoveFirstWidget(); procedure MoveLastWidget(); procedure AddWidget(PWidget:pointer); procedure RenderWidgets(); end; procedure TWidgetContainer.RenderWidgets(); begin MoveFirstWidget(); while (PCurWidget^.next nil) do begin PCurWidget^.widget:=PWidget(PCurWidget^.widget); // cast the pointer to a widget pointer if (PCurWidget^.widget^.meta = 'ENTITY') then // this is line 80

At first glance, this should read
PwidgetSomething(PCurWidget^.widget)^.meta = 'ENTITY' because widget is an untyped pointer ?

And the same for the other line ?

Michael.

Reply by email

Ron Weidner
to Unknown author
Show quoted text 8 lines
At first glance, this should read PwidgetSomething(PCurWidget^.widget)^.meta = 'ENTITY' because widget is an untyped pointer ? And the same for the other line ? Michael.

Thanks Michael. Actually widget is a typed pointer but the problem I was trying to solve is that widget could be one of two different types. I think I solved my problem with the following code, but I will need write a test program to be sure. It compiles so I must be getting close. :)

procedure TWidgetContainer.RenderWidgets();
var
entity:PWidgetEntity;
container:PWidgetContainer;
base:PWidget;
begin
	MoveFirstWidget();
	while (PCurWidget^.next  nil) do
	begin
		base:=PCurWidget^.widget; // cast the pointer to a
widget pointer
		if (base^.meta = 'ENTITY') then
		begin
			PCurWidget^.widget:=PCurWidget^.widget;
			entity:=PCurWidget^.widget;
			entity^.Render();
		end
		else
		begin
			container:=PCurWidget^.widget;
			container^.Render();
		end;
		PCurWidget:=PCurWidget^.next;
		dispose(PHeadWidget);
		PHeadWidget:=PCurWidget;
	end;
end;

Ron_W

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail

Reply by email

Marcel Martin
to Ron Weidner: I thought I was getting closer to understanding pointers but it appears that I'm still…
Ron Weidner wrote 54 lines
I thought I was getting closer to understanding pointers but it appears that I'm still not getting it. I wrote the following code fragment but it doesn't compile. the errors I get are... Widget_container_class.pas(80,27) Error: Illegal qualifier Widget_container_class.pas(88,23) Error: Illegal qualifier Widget_container_class.pas(88,29) Error: Illegal expression Widget_container_class.pas(88,29) Fatal: Syntax error, ";" expected but "(" found I numbered lines 80 and 88 in comments so that the error messages make sense. (to the experienced programmer like yourself :) )Please let me know if you see what the problems are. {$H+} unit Widget_container_class; interface uses Attribute_class,Widget_class,Widget_entity_class,web; type PWidgetList=^TWidgetList; TWidgetList=record widget:pointer; next:PWidgetList; end; type PWidgetContainer=^TWidgetContainer; TWidgetContainer=Object(TWidget) private PCurWidget,PHeadWidget:PWidgetList; text:string; public constructor init(ATag:string); procedure Render(); procedure SetText(str:string); function GetText():string; procedure MoveFirstWidget(); procedure MoveLastWidget(); procedure AddWidget(PWidget:pointer); procedure RenderWidgets(); end; procedure TWidgetContainer.RenderWidgets(); begin MoveFirstWidget(); while (PCurWidget^.next nil) do begin PCurWidget^.widget:=PWidget(PCurWidget^.widget); // cast the pointer to a widget pointer

The previous line is useless. It just sets widget with the value it already has and it does not change the fact that widget is an untyped pointer.

You should rather use
          if PWidget(PCurWidget^.widget)^.meta = 'ENTITY' then

instead of the following line

Show quoted text 12 lines
if (PCurWidget^.widget^.meta = 'ENTITY') then // this is line 80 begin PCurWidget^.widget:=PWidgetEntity(PCurWidget^.widget); end else begin PCurWidget^.widget:=PWidgetContainer(PCurWidget^.widget); end; PCurWidget^.widget^.Render(); //line 88
idem, use    PWidget(PCurWidget^.widget)^.Render();
Show quoted text 5 lines
PCurWidget:=PCurWidget^.next; dispose(PHeadWidget); PHeadWidget:=PCurWidget; end; end;

Reply by email

Anton Tichawa
to Ron Weidner: I thought I was getting closer to understanding pointers but it appears that I'm still…

Hello!

Ron Weidner wrote 86 lines
I thought I was getting closer to understanding pointers but it appears that I'm still not getting it. I wrote the following code fragment but it doesn't compile. the errors I get are... Widget_container_class.pas(80,27) Error: Illegal qualifier Widget_container_class.pas(88,23) Error: Illegal qualifier Widget_container_class.pas(88,29) Error: Illegal expression Widget_container_class.pas(88,29) Fatal: Syntax error, ";" expected but "(" found I numbered lines 80 and 88 in comments so that the error messages make sense. (to the experienced programmer like yourself :) )Please let me know if you see what the problems are. {$H+} unit Widget_container_class; interface uses Attribute_class,Widget_class,Widget_entity_class,web; type PWidgetList=^TWidgetList; TWidgetList=record widget:pointer; next:PWidgetList; end; type PWidgetContainer=^TWidgetContainer; TWidgetContainer=Object(TWidget) private PCurWidget,PHeadWidget:PWidgetList; text:string; public constructor init(ATag:string); procedure Render(); procedure SetText(str:string); function GetText():string; procedure MoveFirstWidget(); procedure MoveLastWidget(); procedure AddWidget(PWidget:pointer); procedure RenderWidgets(); end; procedure TWidgetContainer.RenderWidgets(); begin MoveFirstWidget(); while (PCurWidget^.next nil) do begin PCurWidget^.widget:=PWidget(PCurWidget^.widget); // cast the pointer to a widget pointer if (PCurWidget^.widget^.meta = 'ENTITY') then // this is line 80 begin PCurWidget^.widget:=PWidgetEntity(PCurWidget^.widget); end else begin PCurWidget^.widget:=PWidgetContainer(PCurWidget^.widget); end; PCurWidget^.widget^.Render(); //line 88 PCurWidget:=PCurWidget^.next; dispose(PHeadWidget); PHeadWidget:=PCurWidget; end; end; Ron_W __________________________________ Do you Yahoo!? New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

The type cast actually does nothing at runtime, so the line

        PCurWidget^.widget:=PWidget(PCurWidget^.widget); //

does nothing.

Type casts are just to inform the compiler, at compile time, to accept a type for some variable or constant it would otherwise reject.

So, you have to typecast where you use it, i. e. -everywhere- you use it.

Instead of:

        PCurWidget^.widget:=PWidget(PCurWidget^.widget); //
        if (PCurWidget^.widget^.meta = 'ENTITY') then //

try:

if (PWidget(PCurWidget^.widget)^.meta = 'ENTITY') then //

Note: I don't see the definition of PWidget in your code peace. I assume it's a pointer to a record containing a string member named meta. But in your procedure

 procedure AddWidget(PWidget:pointer);

you use the very same identifier, PWidget, for a variable name. That's a bit confusing.

hth,

Anton.

Reply by email

Ron Weidner
to Anton Tichawa
Show quoted text 11 lines
Note: I don't see the definition of PWidget in your code peace. I assume it's a pointer to a record containing a string member named meta. But in your procedure procedure AddWidget(PWidget:pointer); you use the very same identifier, PWidget, for a variable name. That's a bit confusing.

You are the 2nd person that I've talked to that seemed confused about this. Since I'm very new to pascal programming, I'm concerned that I may have a bad
design. In an attempt to confirm a design problem I'm going to try to explain what I'm trying to do and ask for advice on a better way to do it.

Ok... Basically I have 3 objects that look like
this...

Widget
---------------|----------
| |
Container Widget Entity Widget

One of the defining differances between an Entity
Widget and a Container widget is that a Container
Widget can contain other widgets. (both other
container widgets and entity widgets). So I needed to create a dynamic list (linked list) that could address either a container widget or an entity widget. So I created TWidgetList with the field 'widget' being an untyped pointer. Now that I have this list, I need to add addresses of _existing_ widgets to the list. So, when I call the method...

procedure AddWidget(PWidget:pointer);

I'm referring to a PWidget but I don't know of which type. (container or entity)

During construction of an Entity or Container widget, the string meta is set to identify what type of widget it is. Now later, I can traverse the TWidgetList, read the meta string, cast the widget pointer to the right type and call the correct object methods.
(Render() in this case.)

Is my code the long way around the barn or does it seem to make better sense explained?

Ron_W

__________________________________
Do you Yahoo!?
Read only the mail you want - Yahoo! Mail SpamGuard. http://promotions.yahoo.com/new_mail

Reply by email

Unknown author
to Ron Weidner
Ron Weidner wrote 42 lines
> Note: I don't see the definition of PWidget in your > code peace. I assume > it's a pointer to a record containing a string > member named meta. But in > your procedure > > procedure AddWidget(PWidget:pointer); > > you use the very same identifier, PWidget, for a > variable name. That's a > bit confusing. You are the 2nd person that I've talked to that seemed confused about this. Since I'm very new to pascal programming, I'm concerned that I may have a bad design. In an attempt to confirm a design problem I'm going to try to explain what I'm trying to do and ask for advice on a better way to do it. Ok... Basically I have 3 objects that look like this... Widget ---------------|---------- | | Container Widget Entity Widget One of the defining differances between an Entity Widget and a Container widget is that a Container Widget can contain other widgets. (both other container widgets and entity widgets). So I needed to create a dynamic list (linked list) that could address either a container widget or an entity widget. So I created TWidgetList with the field 'widget' being an untyped pointer. Now that I have this list, I need to add addresses of _existing_ widgets to the list. So, when I call the method... procedure AddWidget(PWidget:pointer); I'm referring to a PWidget but I don't know of which type. (container or entity)

It should be of type Widget.

procedure AddWidget(AWidget : Widget);
During construction of an Entity or Container widget, the string meta is set to identify what type of widget it is.

It is far easier:

  TWidget = Class (..)
  end;
  TEntityWidget = Class(TWidget)
  TContainerWidget = Class(TWidget)

I added the 'T' before the class name. It is good programming practice to prepend type names with T, and pointers to types with P. It helps differentiating between types and variables of a type.

Show quoted text 6 lines
Now later, I can traverse the TWidgetList, read the meta string, cast the widget pointer to the right type and call the correct object methods. (Render() in this case.) Is my code the long way around the barn or does it seem to make better sense explained?

It is, as you say, the long way around the barn (thanks for teaching me a new expression :) ), and can be done much simpler, without the meta field.

when traversing the widget list you can simply do

  ...
  If Widget is TEntityWidget then
    TEntityWidget(Widget).Render // Or whatever. The point is the typecast.
  else if Widget is TContainerWidget then
    TContainerWidger(Widget).DoSomething;  // Here also, typecast.
  ...

Michael.

Reply by email

Anton Tichawa
to Ron Weidner: You are the 2nd person that I've talked to that seemed confused about this. Since I'm…

Hello, Ron!

Ron Weidner wrote 59 lines
>Note: I don't see the definition of PWidget in your >code peace. I assume >it's a pointer to a record containing a string >member named meta. But in >your procedure > > procedure AddWidget(PWidget:pointer); > >you use the very same identifier, PWidget, for a >variable name. That's a >bit confusing. > > You are the 2nd person that I've talked to that seemed confused about this. Since I'm very new to pascal programming, I'm concerned that I may have a bad design. In an attempt to confirm a design problem I'm going to try to explain what I'm trying to do and ask for advice on a better way to do it. Ok... Basically I have 3 objects that look like this... Widget ---------------|---------- | | Container Widget Entity Widget One of the defining differances between an Entity Widget and a Container widget is that a Container Widget can contain other widgets. (both other container widgets and entity widgets). So I needed to create a dynamic list (linked list) that could address either a container widget or an entity widget. So I created TWidgetList with the field 'widget' being an untyped pointer. Now that I have this list, I need to add addresses of _existing_ widgets to the list. So, when I call the method... procedure AddWidget(PWidget:pointer); I'm referring to a PWidget but I don't know of which type. (container or entity) During construction of an Entity or Container widget, the string meta is set to identify what type of widget it is. Now later, I can traverse the TWidgetList, read the meta string, cast the widget pointer to the right type and call the correct object methods. (Render() in this case.) Is my code the long way around the barn or does it seem to make better sense explained? Ron_W

Your design is the right one for the problem, -and- FreePascal supports this design very well. What you seem to miss is the correspondence between your design ideas and FreePascal's syntax and semantics.

Sorry, but before proceeding I ask you to make a decision (because else writing any code examples might be wasting our time):

FreePascal offers two different approaches to your design: Objects and Classes. Objects is what you're using now. Classes are essentially pointers to Objects, but they also simplify the syntax, and they allow pointer types to inherit from each other. This latter capability perfectly addresses the problem of choosing the right type for the parameter X in AddWidget(X). So, before proceeding, please decide if you want to continue using good old Objects, or if you want to switch to the newer and more powerful Classes. If unsure, choose Objects. Also, if you cannot easily change the declaration of a widget because it's legacy software, choose Objects. I'll then post code examples using the approach you choose.

Anton.

Reply by email

Harald Houppermans
to Ron Weidner: I thought I was getting closer to understanding pointers but it appears that I'm still…

Just a general comment:

Have you thought about writing a generic/general linked list unit first and then using that to implement the widget stuff ?

Since writing linked lists can be tricky... best is to make a generic unit for it... test it well... and use it ;)

I can think up some reasons why not to use generic linked lists:

1. Speed reasons. ( Generic lists might be a bit slower because of more procedure calling )

2. Some special linked list stuff is required..

Do any of these reasons apply ?

Bye,
Skybuck.

Reply by email

Ron Weidner
to Harald Houppermans
--- Harald Houppermans wrote 23 lines
Just a general comment: Have you thought about writing a generic/general linked list unit first and then using that to implement the widget stuff ? Since writing linked lists can be tricky... best is to make a generic unit for it... test it well... and use it ;) I can think up some reasons why not to use generic linked lists: 1. Speed reasons. ( Generic lists might be a bit slower because of more procedure calling ) 2. Some special linked list stuff is required.. Do any of these reasons apply ? Bye, Skybuck.

No, there is no reason to not write a generic linked list first. I've considered working on a generic
linked list class as a separate project from the one I'm currently working on. First I would like to see this project through to completion before I start a generic list.

Ron_W

__________________________________
Do you Yahoo!?
Yahoo! Mail - You care about security. So do we.
http://promotions.yahoo.com/new_mail

Reply by email

Ron Weidner
to Anton Tichawa: Hello, Ron! Your design is the right one for the problem, -and- FreePascal supports this…
Show quoted text 36 lines
Your design is the right one for the problem, -and- FreePascal supports this design very well. What you seem to miss is the correspondence between your design ideas and FreePascal's syntax and semantics. Sorry, but before proceeding I ask you to make a decision (because else writing any code examples might be wasting our time): FreePascal offers two different approaches to your design: Objects and Classes. Objects is what you're using now. Classes are essentially pointers to Objects, but they also simplify the syntax, and they allow pointer types to inherit from each other. This latter capability perfectly addresses the problem of choosing the right type for the parameter X in AddWidget(X). So, before proceeding, please decide if you want to continue using good old Objects, or if you want to switch to the newer and more powerful Classes. If unsure, choose Objects. Also, if you cannot easily change the declaration of a widget because it's legacy software, choose Objects. I'll then post code examples using the approach you choose. Anton.

When you put it like that, it seems silly to use
Objects over Classes. I've only written 4 files for this project, and they could probably be easily ported from Objects to Classes. So if what you are saying is that the Classes way of solving this (and like)
problem, and since I have no legacy software to
support, I would love to see a working example of this code done with Classes.

Thankyou.

Ron_W

__________________________________
Do you Yahoo!?
Yahoo! Mail Address AutoComplete - You start. We finish. http://promotions.yahoo.com/new_mail

Reply by email

Anton Tichawa
to Ron Weidner

Hello!

Ron Weidner wrote 55 lines
>Your design is the right one for the problem, -and- >FreePascal supports >this design very well. What you seem to miss is the >correspondence >between your design ideas and FreePascal's syntax >and semantics. > >Sorry, but before proceeding I ask you to make a >decision (because else >writing any code examples might be wasting our >time): > >FreePascal offers two different approaches to your >design: Objects and >Classes. Objects is what you're using now. Classes >are essentially >pointers to Objects, but they also simplify the >syntax, and they allow >pointer types to inherit from each other. This >latter capability >perfectly addresses the problem of choosing the >right type for the >parameter X in AddWidget(X). So, before proceeding, >please decide if you >want to continue using good old Objects, or if you >want to switch to the >newer and more powerful Classes. If unsure, choose >Objects. Also, if you >cannot easily change the declaration of a widget >because it's legacy >software, choose Objects. I'll then post code >examples using the >approach you choose. > >Anton. > > > When you put it like that, it seems silly to use Objects over Classes. I've only written 4 files for this project, and they could probably be easily ported from Objects to Classes. So if what you are saying is that the Classes way of solving this (and like) problem, and since I have no legacy software to support, I would love to see a working example of this code done with Classes. Thankyou. Ron_W

<snip>

program widgets; // free demo of a list of class instances, by Anton
Tichawa.
// first, the common ancestor class, CWidget, is declared.
type CWidget = class(TObject) // TObject is, despite it's name, a class
type here
Tag: String;
constructor Create(ATag: String);
// the destructor, Destroy, defaults to TObject.Destroy
end;
// next, the list. It's still a record, i. e. smaller and faster
compared to classes.
type PWidgetList = ^TWidgetList; TWidgetList = record
Widget: CWidget; // a pointer to an instance of CWidget or a descendant
Next: PWidgetList;
end;
// next, the two descendants of CWidget (inheriting all data and methods
from CWidget):
type CWidgetEntity = class(CWidget) // maybe unused now?
end;
type CWidgetContainer = class(CWidget)
HeadWidgetPtr: PWidgetList;
CurWidgetPtr: PWidgetList;
constructor Create(ATag:string); // constructors need no 'override'
destructor Destroy; override; // overrides, i. e. replaces TObject.Destroy
procedure AddWidget(AWidget: CWidget); // might be a container, too
procedure Print(ALevel: integer);
end;
// 'the' widget container
var TheWidgetContainer: CWidgetContainer; // a pointer to an instance on
the heap
// CWidget methods:
constructor CWidget.Create(ATag: String);
begin
inherited Create; // this calls TObject.Create
Tag := ATag;
end;
// CWidgetContainer methods:
constructor CWidgetContainer.Create(ATag: String);
begin
inherited Create(ATag); // = CWidget.Create, assigns ATag to Tag etc.
CurWidgetPtr := nil;
HeadWidgetPtr := nil;
end;
destructor CWidgetContainer.Destroy;
begin
// caution: here, all deallocation / destruction should be done
inherited Destroy; // call to the inherited Destructor, TObject.Destroy
end;
procedure CWidgetContainer.AddWidget(AWidget: CWidget);
var MyNewListPtr: PWidgetList;
begin
new(MyNewListPtr);
// AWidget might be a widget or a container, but we don't care here
MyNewListPtr^.Widget := AWidget;
MyNewListPtr^.Next := HeadWidgetPtr;
HeadWidgetPtr := MyNewListPtr;
end;
procedure CWidgetContainer.Print(ALevel: integer);
var i: integer;
var indent: String;
var MyWidget: CWidget; // might be a CWidget or CWidgetContainer
begin
// for the sake of simplicity, the printout is reversed. But it's indented:
indent := '';
for i := 0 to ALevel - 1 do begin
indent := indent + ' ';
end;
writeln(indent + 'widget container ' + Tag + ':' );
CurWidgetPtr := HeadWidgetPtr;
repeat
if CurWidgetPtr = nil then break;
MyWidget := CurWidgetPtr^.Widget;
if MyWidget = nil then begin // just to be sure
// InheritsFrom is a method of TObject. This is runtime type info (RTTI).
// We have to check for the more specialized CWidgetContainer first:
end else if MyWidget.InheritsFrom(CWidgetContainer) then begin
// InheritsFrom just told us it's a CWidgetContainer (at runtime). The
// compiler does not know this, and would normally reject the Print
// method. So, we need a type cast:
CWidgetContainer(MyWidget).Print(ALevel + 1);
end else if MyWidget.InheritsFrom(CWidget) then begin
writeln(indent + ' ordinary widget ''' + MyWidget.Tag + ':');
end;
CurWidgetPtr := CurWidgetPtr^.Next;
until false;
end;
var MyWidgetContainer: CWidgetContainer; // a temporary buffer for
sub-containers
begin
// create 'the' widget container
TheWidgetContainer := CWidgetContainer.Create('TheWidgetContainer');
// add some widgets and containers
TheWidgetContainer.AddWidget(CWidget.Create('Widget-A'));
MyWidgetContainer := CWidgetContainer.Create('WidgetContainer-B');
MyWidgetContainer.AddWidget(CWidget.Create('Widget-B1'));
MyWidgetContainer.AddWidget(CWidget.Create('Widget-B2'));
// among other things, a CWidgetContainer is still a CWidget, so the
compiler
// accepts passing MyWidgetContainer without type cast.
TheWidgetContainer.AddWidget(MyWidgetContainer);
TheWidgetContainer.AddWidget(CWidget.Create('Widget-C'));
// print
TheWidgetContainer.Print(0);
// caution: cleaning up (dispose, destroy) not yet implemented ..
end.
//
// the printout reads (GNU/Linux, fpc 1.0.10, sequence of members is
reversed):
//
// widget container TheWidgetContainer:
// ordinary widget 'Widget-C:
// widget container WidgetContainer-B:
// ordinary widget 'Widget-B2:
// ordinary widget 'Widget-B1:
// ordinary widget 'Widget-A:
//

hth,

Anton.

Reply by email