You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ada2012受控类型编译错误:抽象过程调用需调度

Ada编译错误:抽象Initialize与受控成员冲突的解决方案

问题背景

编译错误发生在私有部分Derived_t类型定义处(第33行第8列),错误提示:

call to abstract procedure must be dispatching

触发条件:

  • Derived_t包含Hashed_Maps.Map类型的受控成员dict
  • Derived_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 01:45:02