求助:Ada中泛型包结合动态分发的优雅实现方案
Ada中泛型包结合动态分发的无限递归问题解决方法
你的代码触发无限递归的核心原因是:那个接受Object'Class参数的Print过程不是Object类型的动态分发操作,而是一个独立的重载过程。当你在这个过程里调用X.Print时,编译器会直接匹配到这个过程本身,导致无限调用,最终触发STORAGE_ERROR。
要实现无需条件判断的优雅动态分发,正确的做法是把Print定义为Object类型的抽象操作,让子类重写该操作,利用Ada的动态分发机制自动调用对应子类的实现。
修正后的完整代码如下:
with Ada.Text_IO; procedure Test is type Object is abstract tagged limited null record; -- 将Print声明为Object的抽象操作,支持动态分发 procedure Print (X : access Object) is abstract; type A is limited new Object with null record; type B is limited new Object with null record; generic type T is abstract tagged limited private; with procedure Print (X : access T'Class); package Test_Generics is procedure Call_Print (X : access T'Class); end Test_Generics; package body Test_Generics is procedure Call_Print (X : access T'Class) is begin X.Print; -- 此时会触发动态分发,调用对应子类的Print实现 end Call_Print; end Test_Generics; -- 重写Object的抽象操作,实现A类的打印逻辑 overriding procedure Print (X : access A) is begin Ada.Text_IO.Put_Line ("Print A"); end Print; -- 重写Object的抽象操作,实现B类的打印逻辑 overriding procedure Print (X : access B) is begin Ada.Text_IO.Put_Line ("Print B"); end Print; -- 实例化泛型包时,直接传入Object类型和它的抽象操作 package Impl is new Test_Generics (Object, Print); A1 : access A := new A; B1 : access B := new B; begin Impl.Call_Print (A1); -- 输出 "Print A" Impl.Call_Print (B1); -- 输出 "Print B" end Test;
关键修正点说明:
- 在
Object类型中添加了抽象操作procedure Print (X : access Object) is abstract;,这是动态分发的基础,所有子类必须重写该操作。 - 子类A、B中的
Print过程使用overriding关键字明确标记为重写父类的操作,确保编译器识别为动态分发的一部分。 - 移除了原来那个导致递归的独立
Print (X : access Object'Class)过程,现在X.Print会直接触发动态分发,自动调用对应子类的实现。
这样修改后,泛型包中的Call_Print可以通过动态分发正确调用子类的Print过程,完全不需要if X in A then ...这类条件判断,符合你想要的优雅实现方式。
内容的提问来源于stack exchange,提问作者user1091344
相关产品推荐
相关产品推荐

