Ada2012受控类型编译错误:抽象过程调用需调度
Ada编译错误:抽象Initialize与受控成员冲突的解决方案
问题背景
编译错误发生在私有部分Derived_t类型定义处(第33行第8列),错误提示:
call to abstract procedure must be dispatching
触发条件:
Derived_t包含Hashed_Maps.Map类型的受控成员dictDerived_t的Initialize过程被声明为抽象
当满足以下任一条件时错误消失:
- 为
Derived_t提供Initialize的具体实现 - 移除
Derived_t中的受控成员dict
错误原因分析
Ada.Containers.Hashed_Maps.Map是受控类型,当创建Derived_t实例时,编译器会自动生成代码初始化其受控成员dict,这一过程需要隐式调用Derived_t的Initialize过程。但由于Initialize被声明为抽象,而隐式调用属于静态绑定(非分发调用),编译器无法解析到具体实现,因此抛出错误。
修复方案
核心思路:给Derived_t提供非抽象的Initialize默认实现,同时强制子类必须重写该过程完成实例初始化。
1. 修改包规范,将Initialize改为非抽象
with Ada.Finalization; private with Ada.Containers.Hashed_Maps; private with Ada.Unchecked_Deallocation; package root is type Root_t is limited interface; type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and Root_t with private; overriding procedure Initialize (this : in out Derived_t); -- 移除is abstract,改为非抽象 overriding procedure Finalize (this : in out Derived_t); private type array_t is array (Positive range <>) of Positive; type arrayPtr_t is access array_t; function fHash (key : Positive) return Ada.Containers.Hash_Type is (Ada.Containers.Hash_Type(key)); package HashedDict_pck is new Ada.Containers.Hashed_Maps (Key_Type => Positive, Element_Type => Positive, Hash => fHash, Equivalent_Keys => "="); type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and Root_t with record arrayMember : arrayPtr_t; dict : HashedDict_pck.map; end record; procedure pFreeArray is new Ada.Unchecked_Deallocation (array_t, arrayPtr_t); end root;
2. 在包体中实现默认Initialize,添加强制重写检查
package body root is -------------- -- Initialize -- -------------- overriding procedure Initialize (this : in out Derived_t) is begin -- 检查是否调用基类本身的Initialize(子类未重写) if Derived_t'Class(this)'Tag = Derived_t'Tag then raise Program_Error with "Concrete subtypes must override Initialize"; end if; -- 空实现,子类重写时需完成arrayMember等成员的初始化 end Initialize; -------------- -- Finalize -- -------------- overriding procedure Finalize (this : in out Derived_t) is begin this.dict.Clear; pFreeArray(this.arrayMember); end Finalize; end root;
3. 子类实现(保持原有结构)
子类Concrete_t仍需重写Initialize过程,否则实例化时会触发Program_Error:
package root.concrete is type Concrete_t is new Derived_t with private; overriding procedure Initialize(this : in out Concrete_t); -- 必须实现 -- other Concrete_t public primitives private type Concrete_t is new Derived_t with record --Some stuff end record; end root.concrete;
方案说明
- 非抽象的
Initialize默认实现解决了编译器隐式调用的问题,确保受控成员dict能被正常初始化。 - 通过标签检查强制子类必须重写
Initialize,避免子类依赖基类空实现导致未初始化成员(如arrayMember)引发运行时错误。
内容的提问来源于stack exchange,提问作者Albatros23
相关产品推荐
相关产品推荐

