April 20, 2024, 09:06:30 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Pointers

Started by LarryMc, January 09, 2006, 07:20:00 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

LarryMc

Is it (or will it be) possible to program sophisticated programs (multi-window/multi-dialog) in Aurora using all the various controls WITHOUT using pointers!?
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Pointers are a fact of programming.  Even using a string your using a pointer.  And a pointer is just a variable that holds an address.  A reference is a pointer by another name.  In assembly you using pointers more than anything else.

And since Aurora is a C like langauge it uses them a bit more than you might be used to in BASIC.

Aurora in its current stage of development can create more sophisticated programs than IBasic will ever be able to.  You just have to learn the syntax, and take your time planning out how your going to manage your classes.

But don't despair.  Global classes will work soon enough, and although they are considered a programming no-no, they do make it a touch easier for beginners to grasp oop programming.  Be warned however that over using globally defined classes will eventually bite you in the end.

Paul.
Ionic Wind Support Team

Doc

<Bump!>

As one who generally writes very simple programs primarily for my own use, I've always avoided the use of pointers. Although I have a general understanding of how they work, to date I've had no good reason(s) to go there. ;)

In considering a new project that will be somewhat more complex in terms of raw processing power requirements, a few questions to mind.

What are the greatest benefits of using pointers from a functional standpoint?

Raw speed...
Coding flexibility...
Both?

Something else altogether...

I guess what I'm asking is "why and when" should a person incorporate them and what benefits are to be gained by doing so?

To date, much of what I've tried with Aurora (admittedly not a lot yet) has by the nature of my coding experience, involved a hefty learning curve. The same can be said for many of the other languages I use as well. Looking ahead at some of the stuff I'd like to use Aurora for, I figure that maybe it's time for me to try and tackle pointer usage as well.

-Doc-

kryton9

Trying to get a better grasp of pointers.
Trying out some crazy combos of what looks like should work.

You will see what I found out and only 1 of the 5 works as expected?

global sub main ()
{
ÂÃ,  int numbers[5];
ÂÃ,  int * p;
ÂÃ,  p = numbers;ÂÃ,  *p = 10;ÂÃ,  ÂÃ,  // element 0ÂÃ,  ÂÃ,  junk value
ÂÃ,  p++;ÂÃ,  *p = 20;ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  // element 1ÂÃ,  ÂÃ,  junk value
ÂÃ,  p = &numbers[2];ÂÃ,  *p = 30;// element 2ÂÃ,  ÂÃ,  this is the only 1 that has a correct value
ÂÃ,  //p = numbers + 3;ÂÃ,  *p = 40;// element 3ÂÃ,  this causes a crash
ÂÃ,  //p = numbers;ÂÃ,  *(p+4) = 50;// element 4ÂÃ,  this gives error
ÂÃ,  for (int n=0; n<5; n++)
ÂÃ,  {
ÂÃ,  print(numbers[n]);
ÂÃ,  }
ÂÃ,  while GetKey(true) = "";
ÂÃ,  return 0;
}
/* should get output of:
10
20
30
40
50
*/

Ionic Wind Support Team

Pointer math in Aurora is always bytewise.  The type is not used.

Sou you have to do the calculation yourself.

p+=len(int);

Or knowing the size of your data you can access the elements.

*(p+index * size) = value;

Ionic Wind Support Team

kryton9

August 07, 2006, 11:12:45 PM #5 Last Edit: August 07, 2006, 11:22:42 PM by kryton9
In trying to help understand the options available to us with pointers and classes, I got thoughts to put out and was wondering if my thinking is correct?

1. If the programmer wanted to make a class work without having to pass parameters to all the methods, would he then have to setup pointers to all the variables needed?

ÂÃ,  ÂÃ,  A. If so, then where in the implementation would they belong, in the constructor orÂÃ,  some sort of create methods?

2.ÂÃ,  Instead of using a new() to initialize a pointer, is there another way... not sure if I can ask the question correctly, but would the following be the same thing if I had a class MyWindow.
ÂÃ,  ÂÃ,  ÂÃ, MyWindow *mw;ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ, would that be the same as mw = new(MyWindow);
ÂÃ,  ÂÃ, 
ÂÃ,  ÂÃ,  A. If so, is one way better than the other?

3.ÂÃ,  If I wanted to make a program all objects and classes and instead of having general global variables above the global sub main() , how or where would something like that be placed in an all OOP type program?
Would you create a class that would become a base class to all your other classes that had pointers to those variables or could they just be member variables and be seen by the derived classes, if it was done that way even?

Ionic Wind Support Team

Um. No.

NEW just allocates memory, it doesn't really care what the memory is used for.  With the exception that it inserts code to call the class constructor.  So when you use:

CWindow *mw =  NEW(CWindow, 1);

the following happens:

NEW(CWindow,1) gets translated by the parser into a call to a lower level function __new, and then a function call to the constructor.  It's really done in assembly but would look like this in Aurora.

CWindow *mw = __new(TYPE_USER, LEN(CWindow) * 1);
mw->CWindow();  //compiler inserted

As I have stated before classes are more related to structures (udt's) then you might think.  The size of a class returned by LEN is the size of all the member variables of that class, including the hidden vtable pointer.  Just as the size of a structure is the size of its member variables.

When you call DELETE it translates to __delete which and calls the class destructor.

DELETE(mw); becomes:

mw->_CWindow();
__delete(mw);

MyWindow *mw;

Is just defining a pointer variable.  It is not initialized until you assign it.  Using it without assigning it with NEW or the address of an exisiting class wil give you an exception.

MyWindow mw;

Is defining a variable of type MyWindow.  Not much different then defining a variable of a structure type.  The compiler inserts the call to the constructor using the '.' notation, because it knows it's a class.  This is also done in assembly, but in Aurora it would look like:

mw.CWindow();

When the variable goes out of scope, meaning your code is at the end of the subroutine it is contained in, the compiler inserts the call to the destructor, right before any RETURN statement.  All invisible to you bit it works.

Sub MySub()
{
    CWindow mw;
    mw.CWindow(); //compiler inserted
    ....
    ....
    mw._CWindow(); // compiler inserted
    return;
}

So in order to use classes you either have to define them within a subroutine (local stack variable) or allocate them with NEW. 

Quote
If the programmer wanted to make a class work without having to pass parameters to all the methods, would he then have to setup pointers to all the variables needed?

Sorry you lost me on that one.
Ionic Wind Support Team

kryton9

August 07, 2006, 11:55:37 PM #7 Last Edit: August 08, 2006, 12:05:27 AM by kryton9
I can see I am lost, I thought I had a grasp on this when I did those baby steps, I guess came out a few steps too short to make it to harder applications.
I am going to tinker with the fraggs example and see if I can get this sorted out in my mind. Thanks for the explanation. I understood, but still not clear in my mind's eye.
Will keep plugging away.

In the fragg's example, couldn't structure fraggs have been a class and most of the methods in The App been the methods to a fragg's class?ÂÃ,  And where the members of the structure were members of the class fraggs?

In the example as it is, are the variables in the constructor then considered global variables and seen by all the methods?ÂÃ,  I noticed some are declared as member variables in the definition, but not others, is that what separates what is seen by whom within the methods?

Also, why is void used here: void *pos = frags.GetFirst();ÂÃ,  ÂÃ, The type is known isn't it? It is getting back a pointer?

Ionic Wind Support Team

August 08, 2006, 12:51:11 AM #8 Last Edit: August 08, 2006, 12:53:08 AM by Paul Turley
GetFirst doesn't return the data in the list.  It returns an untyped pointer to the first node.  If you have the source code the linked list classes are in acommon.lib.  Not much different from the implementation in other languages. 

GetData returns a pointer to the known data which is why you see:

Frag *f = frags.GetData(pos);

Quote
In the fragg's example, couldn't structure fraggs have been a class and most of the methods in The App been the methods to a fragg's class?

Not everything needs to be a class just because your using an OOP language.  Using a structure and a linked list fit the problem in the  most convenient fashion.  Making a 'frag' class would have been overkill for the example.

A class is is a good fit if it is a base to other classes, derived from an exisiting class, or uses another existing class in such a manner that it would be inconvenient to use discrete functions.

For example C2DScreen is a class because it derives and inherits the funcitonality of the CWindow class.  Which makes sense since a graphics screen is really just a window anyway. 

Just as all controls derive from CControl which derives from CWindow.  All controls are windows, and all controls have some things in common like text (captions) and colors. 

Colleges like to teach the building block approach.  Generally they use something real world like companies and their employees.  Youre given the task of creating a class library that manages employees, has to account for different types of employees, and can easily be added on to when a new job description is created.  So you think that an employee is a person, a person has certain data associated with him/her such as name, age, SSN, address, etc. 

You start out by just defining classes and their data.  Then add needed methods.

class CPerson
{
     string name;
     int age;
     string address;
     string SSN;
}

class CEmployee: CPerson
{
    int EmployeeID;
    float salary;
    string title;
}

class CManager : CEmployee
{
    string division;
    int subbordinates;
}

class CTopDog: CManager
{
    float bonus;
}

OOP polymorphism/abstraction (look it up) allows passing an object to a method/function even if you only have a pointer typed to the base class. So lets say you have to calculate total payroll.  And the employees are all stored in a linked list, that list contains a mix of CManager and CEmployee data.  If you were using procedural style then you might have just a single structure with a 'type' member.  TYPE_MANAGER, TYPE_CEO, etc.  Using OOP is more seamless.

sub CalculatePayroll(CPointerList *empList)
{
     float total = 0.0;
     void *pos = empList->GetFirst();
     while(pos)
     {
          CEmployee *emp = empList->GetData(pos);
          total += emp->salary;
     }
}

It doesn't matter if the data added to the list was NEW(CEmployee,1) or NEW(CManager,1) or NEW(CTopDog,1).  Since CManager and CTopDog are derived from CEmployee they are a 'type of' CEmployee.  And you can access the salary member variable without even knowing the real type of the class.

Read up on the subject.  I've discussed it in length on the forums and this very basic discussion only scratches the surface.
Ionic Wind Support Team

kryton9

THanks, have been reading up on it, that is why so confused :)

Just have to build up on the experience part and when experimenting I run into so many errors, I kept experimenting and then try to boil down the concepts into a few questions and then ask, so believe me you are only seeing a brief part of the confusion I am in after many hours of experimenting on my own :)

kryton9

Well, back to a question about pointers.

This works:

CEdit *EditBox;
.
.
.
EditBox = GetControl(EDIT_5);
temp = EditBox->GetText();

Is there a way for me to do this so I don't have to use -> and can just use the . by defining CEdit *EditBox some other way?
temp = EditBox.GetText();

Ionic Wind Support Team

No.  Unless you like using type casting and the * operator.

temp = *editBox.GetText();

Is the equivelent. The '.' operator accesses the member directly.  The -> dereferences a pointer and then accesses the member (class member, structure member, method, etc).  Which is the same as using the * to dereference first and then using the '.' operator. 

If you're sure the control exisits you can also do:

temp = GetControl(EDIT_5)->GetText();

Since the GetText method is a member of the base class CControl.  GetControl returns a pointer to a CControl derived class.  I highly recommend, however,  that you always check for valid pointers though as the code above will fail if the control doesn't exist.  You never know what conditions your programs will be run under and under severe memory load I have seen controls fail to create on low end systems.  The proper coding, for a production environment would be:

CEdit *editBox;
editBox = GetControl(EDIT_5);
if( editBox != NULL)
{
     temp = EditBox->GetText();
     //other operations with the pointer
}
else
{
     //report the failure to the user.  Give them a chance to save work, etc.
}

Paul.

P.S.  Get used the the ->  You will be typing it a lot and it will be second nature after a while ;)
Ionic Wind Support Team

kryton9

Thanks a lot Paul, I don't mind typing -> , just wanted to make sure I understood the options available in using pointers and how it all worked. I tried to use typecasting but I was making it harder than you showed me. I tried:  *(CEdit) EditBox  :)

Yes, I do need to start checking for error conditions and if things exist or not, that is a giant fault in my programming. Thanks for the nice explanation
and examples.