简体   繁体   English

受控单例变量的Ada初始化

[英]Ada initialization of controlled singleton variable

I am trying to create a package with a singleton variable that is auto initialized. 我试图用自动初始化的单例变量创建一个包。 If the singleton variable is not a controlled type, then the compiler doesn't complain, but when I make it controlled, I get the warning:"cannot call Initialize before body seen" 如果单例变量不是受控类型,则编译器不会抱怨,但是当我将其设为受控类型时,我会收到警告:“无法在看到正文之前调用初始化”

Followed by: "Program error will be raised at run time." 后跟:“程序错误将在运行时引发。”

So, I think the compiler wants the singleton variable to be hidden from child objects, but this is not what I want. 因此,我认为编译器希望从子对象中隐藏单例变量,但这不是我想要的。 Here's my code: 这是我的代码:

with Ada.Finalization;

package static_member is
   type singleton_type is tagged limited private;

private
   type singleton_type is new Ada.Finalization.Limited_Controlled with record
      data_to_init: Natural;
   end record;

   overriding procedure Initialize(data: in out singleton_type);
   overriding procedure Finalize(data: in out singleton_type);

   --This is where I get the warnings.
   --I want singleton to be visible to child objects.
   singleton: singleton_type;
end static_member;

Then the package body is: 那么包主体是:

package body static_member is
   overriding procedure Initialize(data: in out singleton_type) is
   begin
      data.data_to_init := 0;
   end Initialize;

   overriding procedure Finalize(data: in out singleton_type) is null;
end static_member;

How would I create a singleton variable that is initialized, and ready to use by the time object instances begin to be created? 我将如何创建一个已初始化的单例变量,并准备在对象实例开始创建时使用? Thanks in advance. 提前致谢。

The answer to this question as posed is that - as the compiler said - "cannot call Initialize before body seen"; 提出的这个问题的答案是-正如编译器所说的-“不能在看到正文之前调用Initialize”。 that is, the place in the program text where Initialize is called must be after the place in the program text where the body of Initialize is found. 也就是说,程序文本中调用Initialize的位置必须在程序文本中找到Initialize主体的位置之后。 This is a (maybe historical) consequence of a desire for one-pass compilers . 这是对单遍编译器的渴望(可能是历史性的)结果。

Because the body of Initialize has to appear in the body of the package (unless it's null, which is legal in Ada 2012), this means that singleton can only be declared in the package body ( after the body of Initialize , of course). 由于Initialize的正文必须出现在包的正文中(除非为null,这在Ada 2012中是合法的),这意味着singleton只能在包正文中声明(当然,在Initialize的正文之后 )。

This means that you need to provide access subprograms for use by child packages: possibly 这意味着您需要提供子程序包使用的访问子程序:可能

with Ada.Finalization;
package Static_Member with Elaborate_Body is
   type Singleton_Type is tagged limited private;
   function Singleton return access Singleton_Type;
private
   type Singleton_Type is new Ada.Finalization.Limited_Controlled with record
      Data_To_Init: Natural;
   end record;

   overriding procedure Initialize (Data: in out Singleton_Type);
   overriding procedure Finalize (Data: in out Singleton_Type);
end Static_Member;

package body Static_Member is
   overriding procedure Initialize (Data: in out Singleton_Type) is
   begin
      Data.Data_To_Init := 0;
   end Initialize;

   overriding procedure Finalize (Data: in out Singleton_Type) is null;

   The_Singleton: aliased Singleton_Type;

   function Singleton return access Singleton_Type is (The_Singleton'Access);
end Static_Member;

The reason for the Elaborate_Body is that, without it, the compiler doesn't have to elaborate the package body before other, using, packages that call package subprograms (eg Singleton ): so Elaborate_Body的原因是,没有它,编译器不必在使用其他调用程序包子程序的程序包(例如Singleton )之前就详细说明程序包主体:

The_Singleton: aliased Singleton_Type;

with the implicit call to Initialize might not have happened (which would lead to a Program_Error with a different cause, known in the trade as "access before elaboration" or ABE). 可能不会发生对Initialize的隐式调用(这将导致Program_Error出现其他原因,在行业中称为“详细说明之前访问”或ABE)。


That said, there are other approaches, which avoid the use of Ada.Finalization . 也就是说,还有其他方法可以避免使用Ada.Finalization Your sample code doesn't show any particular reason to use it, and indeed there's no point in overriding Finalize (unless you want something to happen at program shutdown?) 您的示例代码没有显示使用它的任何特殊原因,并且实际上没有必要覆盖Finalize (除非您希望在程序关闭时发生某些事情?)

One possibility (for a simple case) would be to declare Singleton_Type with initialization: 一种可能的情况(对于简单情况)是使用初始化声明Singleton_Type

type Singleton_Type is record
   Data_To_Init : Natural := 0;
end record;

An alternate would be to do the initialization in the package body: 另一种方法是在程序包主体中进行初始化:

package Static_Member with Elaborate_Body is
   type Singleton_Type is limited private;
   function Singleton return access Singleton_Type;
private
   type Singleton_Type is limited record
      Data_To_Init : Natural;
   end record;
end Static_Member;

package body Static_Member is
   The_Singleton: aliased Singleton_Type;

   function Singleton return access Singleton_Type is (The_Singleton'Access);
begin
   The_Singleton.Data_To_Init := 0;
end Static_Member;

想到的解决方法是:如果动态内存没有障碍,则可以在包主体中分配对象,并可以访问而不是常规实例供孩子查看。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM