comp.lang.ada
 help / color / mirror / Atom feed
From: Ludovic Brenta <ludovic@ludovic-brenta.org>
Subject: Re: Pointers explained?
Date: Mon, 30 Jul 2007 21:05:15 +0200
Date: 2007-07-30T21:05:15+02:00	[thread overview]
Message-ID: <87vec1hfv8.fsf@ludovic-brenta.org> (raw)
In-Reply-To: 1185818189.689914.159900@x40g2000prg.googlegroups.com

shaunpatterson@gmail.com writes:
> Hi
>
>    I'm still relatively new to Ada -- coming from a strong C++
> background.  Some of this may seem stupid - and feel free to point it
> out to me.  I am using Ada 95 - GNAT Pro 3.16a1
>
> I have a message factory I've been screwing around with (converting
> it from Ada to C++).
>
> I basically have an abstract message type:
>
> type Message is abstract tagged null record;
> type Message_Class is access all Message'Class;
>
> then all other messages are derived from this.
>
> Now from my factory create method, I'm returning a Message_Class.
> This message_class is stored in another record to be handled again
> later:
>
> type CallbackEvent is
> record
>      msg : Message_Class;
>      ...
> end record;
>
>
> Now my basic problem -- or not really a problem -- is that to create
> the Message_Class I have to use "new" and allocate and deallocate
> memory.
>
> Now - my solution was to re-write my message factory to return a
> type Message'Class.  However, I went to change my callback structure
> to:
>
> type CallbackEvent is
> record
>     msg : Message'Class
> end record;
>
> and I get the message "unconstrained subtype in component declaration"
>
> So, I'm assuming the compiler just doesn't know how to big this
> message is.  that's why I believe i should use a pointer (the
> Message_Class type) However, I cannot find a way of converting
> between a Message'Class to a Message_Class;
>
> It appears that the only way to get a Message_Class is by some where
> in the code using a "new"
>
> Is this assumption correct?

I think this is both a language issue and a design issue.

From the language standpoint, your assumption would be correct had you
declared Message_Class thus:

type Message_Class is access Message'Class;

This declares a "pool-specific" access type, and the only way to
create values of this type is by calling "new" which will allocate
from a storage pool (there is a default storage pool, but you could
create your own).  But, your actual declaration reads:

type Message_Class is access all Message'Class;

The "all" keyword makes this a "general" access type, meaning it can
take access values of objects that are in any pool, or on the stack,
or in the data segment.  So, there are two ways to create values of
this type: with "new" or by means of the Access attribute, like this:

declare
   M : aliased Message'Class := Factory; -- Note: M is on the stack
   Event : Callback_Event := (Msg => M'Access);
begin
   ...
end;

Note that, before you can take the 'Access of an object such as M, you
must declare it as aliased.  (In C++, everything is implicitly
aliased.  In Ada, aliasing is explicit and only occurs when you say it
does).

Now, from a design standpoint, I don't think you really want to record
access values for Messages on the stack or data segment, do you?  In
which case, the pool-specific access type and mandatory call to "new"
are really what you want.  So, how about this:

type Message is abstract tagged null record;
type Message_Class is access Message'Class;

type Message_Type is (A, B, C);

function Factory (Kind : Message_Type) return Message_Class is
begin
   case Kind is
      when A => return new Message_A'(...);
      when B => return new Message_B'(...);
      when C => return new Message_C'(...);
   end case;
end Factory;

function Factory (Kind : Message_Type) return Callback_Event is
begin
   return (Msg => Factory (Kind), ...);
end Factory;

HTH

-- 
Ludovic Brenta.



  parent reply	other threads:[~2007-07-30 19:05 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-30 17:53 Pointers explained? shaunpatterson
2007-07-30 17:56 ` shaunpatterson
2007-07-30 19:04   ` Ed Falis
2007-07-30 19:05   ` Ludovic Brenta [this message]
2007-07-30 19:36   ` Adam Beneschan
2007-07-30 21:23     ` Maciej Sobczak
2007-07-30 22:36       ` Adam Beneschan
2007-07-31  7:33         ` Dmitry A. Kazakov
2007-07-31  1:15       ` Anh Vo
2007-07-30 22:20     ` Adam Beneschan
2007-07-30 21:31   ` Jeffrey R. Carter
2007-07-31 17:21   ` Simon Wright
2007-07-31 18:06     ` Dmitry A. Kazakov
2007-07-31 22:38       ` shaunpatterson
2007-08-01  7:53         ` Martin Krischik
2007-08-01  8:21         ` Dmitry A. Kazakov
2007-08-10 19:52         ` Simon Wright
2007-07-30 20:11 ` Dmitry A. Kazakov
2007-07-31  8:28 ` Martin Krischik
  -- strict thread matches above, loose matches on Subject: below --
2007-07-30 17:53 shaunpatterson
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox