Мой вопрос содержит более длинный фрагмент кода Ады.В основном я пытался смоделировать сообщение с заголовком объектно-ориентированным способом.Две примитивные операции Create_Message
и Create_Message_Access
могут использоваться для создания конкретных объектов сообщений.Я не совсем уверен, должна ли примитивная операция возвращать тип Message_Type
или Message_Type_Access
.Какой тип рекомендуется (эффективность?) Или оба решения не оптимальны?
Я думаю, что первым способом объект создается в стеке, а затем копируется после выполнения оператора return
, поскольку переменная Object
выходит за рамки.Правильно или нет?
function Create_Message (Title : String) return Message_Type is
Object : Message_Type;
begin
Object.Title := To_Unbounded_String (Title);
return Object;
end Create_Message;
Я думаю, что во втором случае объект создается в куче, а затем указатель копируется после выполнения оператора return
, поскольку переменная Object
выходит за рамки.Правильно или нет?
function Create_Message_Access (Title : String) return Message_Type_Access is
Object : Message_Type_Access := new Message_Type;
begin
Object.Title := To_Unbounded_String (Title);
return Object;
end Create_Message_Access;
Позже я создал пример объекта с заголовком, использовал примитивную операцию Updated_Title
, чтобы изменить заголовок и вернуть его обратно в конце.
First_Message := Message.Create_Message ("First");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
First_Message.Update_Title ("First changed");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
First_Message.Update_Title ("First");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
Вывод (как и ожидалось):
First
First changed
First
Затем я сохранил сообщение в векторном контейнере и попытался изменить заголовок, перебирая элементы, хранящиеся в векторе.Я обнаружил, что заголовок сохраняет старое значение, поэтому я предполагаю, что вызов операции Message_Vector.Element (Message_Cursor)
возвращает только копию сообщения, хранящегося в векторе.Правильно или нет?
Messages.Append (First_Message);
Message_Cursor := Message_Vector.First (Messages);
while Message_Vector.Has_Element (Message_Cursor) loop
declare
Temporary_Message : Message.Message_Type;
begin
Temporary_Message := Message_Vector.Element (Message_Cursor);
Temporary_Message.Update_Title ("First changed");
end;
Message_Vector.Next (Message_Cursor);
end loop;
Message_Cursor := Message_Vector.First (Messages);
while Message_Vector.Has_Element (Message_Cursor) loop
--
-- Prints "First" and not "First changed"
--
Ada.Text_IO.Put_Line (Message_Vector.Element (Message_Cursor).Get_Title);
Message_Vector.Next (Message_Cursor);
end loop;
Последний вопрос: в чем разница между Second_Message.all.Get_Title
и Second_Message.Get_Title
?
Second_Message := Message.Create_Message_Access ("Second");
Ada.Text_IO.Put_Line (Second_Message.all.Get_Title);
Ada.Text_IO.Put_Line (Second_Message.Get_Title);
Полный исходный код:
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;
procedure Main is
package Message is
type Message_Type is tagged private;
type Message_Type_Access is access Message_Type;
function Create_Message (Title : String) return Message_Type;
function Create_Message_Access (Title : String) return Message_Type_Access;
function Get_Title (Self : Message_Type) return String;
procedure Update_Title (Self : in out Message_Type; Title : String);
function "=" (Left, Right : Message_Type) return Boolean;
private
type Message_Type is tagged record
Title : Unbounded_String;
end record;
end Message;
package body Message is
function Create_Message (Title : String) return Message_Type is
Object : Message_Type;
begin
Object.Title := To_Unbounded_String (Title);
return Object;
end Create_Message;
function Create_Message_Access (Title : String) return Message_Type_Access is
Object : Message_Type_Access := new Message_Type;
begin
Object.Title := To_Unbounded_String (Title);
return Object;
end Create_Message_Access;
function Get_Title (Self : Message_Type) return String is
begin
return To_String (Self.Title);
end Get_Title;
procedure Update_Title (Self : in out Message_Type; Title : String) is
begin
Self.Title := To_Unbounded_String (Title);
end Update_Title;
function "=" (Left, Right : Message_Type) return Boolean is
begin
return Left.Title = Right.Title;
end "=";
end Message;
package Message_Vector is new Ada.Containers.Vectors (Index_Type => Natural,
Element_Type => Message.Message_Type, "=" => Message."=");
package Message_Access_Vector is new Ada.Containers.Vectors (Index_Type => Natural,
Element_Type => Message.Message_Type_Access, "=" => Message."=");
Messages : Message_Vector.Vector;
Message_Cursor : Message_Vector.Cursor;
Messages_Access : Message_Access_Vector.Vector;
Message_Access_Cursor : Message_Access_Vector.Cursor;
First_Message : Message.Message_Type;
Second_Message : Message.Message_Type_Access;
begin
First_Message := Message.Create_Message ("First");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
First_Message.Update_Title ("First changed");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
First_Message.Update_Title ("First");
Ada.Text_IO.Put_Line (First_Message.Get_Title);
--
Ada.Text_IO.New_Line;
Messages.Append (First_Message);
Message_Cursor := Message_Vector.First (Messages);
while Message_Vector.Has_Element (Message_Cursor) loop
declare
Temporary_Message : Message.Message_Type;
begin
Temporary_Message := Message_Vector.Element (Message_Cursor);
Temporary_Message.Update_Title ("First changed");
end;
Message_Vector.Next (Message_Cursor);
end loop;
Message_Cursor := Message_Vector.First (Messages);
while Message_Vector.Has_Element (Message_Cursor) loop
--
-- Prints "First" and not "First changed"
--
Ada.Text_IO.Put_Line (Message_Vector.Element (Message_Cursor).Get_Title);
Message_Vector.Next (Message_Cursor);
end loop;
--
Ada.Text_IO.New_Line;
Second_Message := Message.Create_Message_Access ("Second");
Ada.Text_IO.Put_Line (Second_Message.all.Get_Title);
Ada.Text_IO.Put_Line (Second_Message.Get_Title);
--
Ada.Text_IO.New_Line;
Messages_Access.Append (Second_Message);
Message_Access_Cursor := Message_Access_Vector.First (Messages_Access);
while Message_Access_Vector.Has_Element (Message_Access_Cursor) loop
declare
Temporary_Message : Message.Message_Type_Access;
begin
Temporary_Message := Message_Access_Vector.Element (Message_Access_Cursor);
Temporary_Message.Update_Title ("Second changed");
end;
Message_Access_Vector.Next (Message_Access_Cursor);
end loop;
Message_Access_Cursor := Message_Access_Vector.First (Messages_Access);
while Message_Access_Vector.Has_Element (Message_Access_Cursor) loop
Ada.Text_IO.Put_Line (Message_Access_Vector.Element (Message_Access_Cursor).Get_Title);
Message_Access_Vector.Next (Message_Access_Cursor);
end loop;
end Main;