|Ada 95 Quality and Style Guide||Chapter 5|
5.4.6 Aliased Objects
Minimize the use of aliased variables.
Use aliasing for statically created, ragged arrays (Rationale 1995, §3.7.1).
Use aliasing to refer to part of a data structure when you want to hide the internal connections and bookkeeping information.
examplepackage Message_Services is type Message_Code_Type is range 0 .. 100; subtype Message is String; function Get_Message (Message_Code: Message_Code_Type) return Message; pragma Inline (Get_Message); end Message_Services; package body Message_Services is type Message_Handle is access constant Message; Message_0 : aliased constant Message := "OK"; Message_1 : aliased constant Message := "Up"; Message_2 : aliased constant Message := "Shutdown"; Message_3 : aliased constant Message := "Shutup"; . . . type Message_Table_Type is array (Message_Code_Type) of Message_Handle; Message_Table : Message_Table_Type := (0 => Message_0'Access, 1 => Message_1'Access, 2 => Message_2'Access, 3 => Message_3'Access, -- etc. ); function Get_Message (Message_Code : Message_Code_Type) return Message is begin return Message_Table (Message_Code).all; end Get_Message; end Message_Services;
The following code fragment shows a use of aliased objects, using the attribute 'Access to implement a generic component that manages hashed collections of objects:generic type Hash_Index is mod <>; type Object is tagged private; type Handle is access all Object; with function Hash (The_Object : in Object) return Hash_Index; package Collection is function Insert (Object : in Collection.Object) return Collection.Handle; function Find (Object : in Collection.Object) return Collection.Handle; Object_Not_Found : exception; ... private type Cell; type Access_Cell is access Cell; end Collection; package body Collection is type Cell is record Value : aliased Collection.Object; Link : Access_Cell; end record; type Table_Type is array (Hash_Index) of Access_Cell; Table : Table_Type; -- Go through the collision chain and return an access to the useful data. function Find (Object : in Collection.Object; Index : in Hash_Index) return Handle is Current : Access_Cell := Table (Index); begin while Current /= null loop if Current.Value = Object then return Current.Value'Access; else Current := Current.Link; end if; end loop; raise Object_Not_Found; end Find; -- The exported one function Find (Object : in Collection.Object) return Collection.Handle is Index : constant Hash_Index := Hash (Object); begin return Find (Object, Index); end Find; ... end Collection;
Aliasing allows the programmer to have indirect access to declared objects. Because you can update aliased objects through more than one path, you must exercise caution to avoid unintended updates. When you restrict the aliased objects to being constant, you avoid having the object unintentionally modified. In the example above, the individual message objects are aliased constant message strings so their values cannot be changed. The ragged array is then initialized with references to each of these constant strings.
Aliasing allows you to manipulate objects using indirection while avoiding dynamic allocation. For example, you can insert an object onto a linked list without dynamically allocating the space for that object (Rationale 1995, §3.7.1).
Another use of aliasing is in a linked data structure in which you try to hide the enclosing container. This is essentially the inverse of a self-referential data structure (see Guideline 5.4.7). If a package manages some data using a linked data structure, you may only want to export access values that denote the "useful" data. You can use an access-to-object to return an access to the useful data, excluding the pointers used to chain objects.
|< Previous Page||Search||Contents||Index||Next Page >|