Dynamic Dispatching in Ada with Access Types

江枫思渺然 提交于 2021-01-29 03:52:22

问题


I am trying to create a package that has Dynamic dispatching using access types. I have achieved Dynamic Dispatching using Class Types using This Q/A as a guide.

I keep getting a compilation error that says: cannot call abstract subprogram. This makes me think that the compiler either doesnt recognize the specialized subprogram, or doesnt recognize the type as a specialized type. But both seem right to me... I dont get it.

main.2.ada

with Ada.Text_IO;
with Animal.Cat;

procedure Main is
    Tabby        : aliased Animal.Cat.Cat_t;
    Animal_Ref   : Animal.Any_Animal_Ptr := Tabby'Unchecked_Access;
    Result       : Boolean;
begin
    Animal.Stroke_Fur (Animal => Animal_Ref.all);

    Result := Animal.Is_Happy(Ptr => Animal_Ref);

    Ada.Text_IO.Put_Line ("Happy Animal = " & Boolean'Image (Result));

end Main;

animal.1.ada

package Animal is

    type base_t is abstract tagged limited null record;

    type Animal_t is abstract new 
        base_t with private;

    type Any_Animal_Ptr is access all Animal_t'Class;
    ----
    procedure Stroke_Fur (Animal : in out Animal_t) is abstract;
    ----
    function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;

private

    type Animal_t is abstract new base_t with 
    record
        Index : integer;
    end record;

end Animal;

animal.cat.1.ada

package Animal.Cat is

    type Cat_t is new Animal.Animal_t with private;
    type Cat_Ptr is access all Cat_t;

    ----
    procedure Stroke_Fur (Cat : in out Cat_t);
    ----
    function Is_Happy (Ptr : in Cat_Ptr) return Boolean;

private
    type Cat_t is new Animal.Animal_t with 
    record
        Purr : Boolean := False;
    end record;            

end Animal.Cat;

animal.cat.2.ada

package body Animal.Cat is

    ----
    procedure Stroke_Fur (Cat : in out Cat_t) is
    begin
        Cat.Purr := True;
    end Stroke_Fur;
    ----
    function Is_Happy (Ptr : in Cat_Ptr) return Boolean is
    begin
        return Ptr.Purr;
    end Is_Happy;

end Animal.Cat;

Error

main.2.ada:13:21: cannot call abstract subprogram "Is_Happy"


回答1:


function Is_Happy (Ptr : in Any_Animal_Ptr) return boolean is abstract;

isn’t a primitive operation (ARM3.2.3(2)) of Animal_t, and so it isn’t dispatching; it’s merely an abstract subprogram (which therefore can’t be called).

Why would you want to make a non-dispatching subprogram abstract? Perhaps you might have a type Metres, in which case the predefined ”*” is inappropriate (multiplying two distances in metres returns an area, not a distance) and you might want to make it abstract to prevent inadvertent misuse.

Anyway, you can declare a primitive operation of Animal_t using accesses as

function Is_Happy (Ptr : access Animal_t) return boolean is abstract;

and then for cats

function Is_Happy (Ptr : access Cat_t) return Boolean;

(or even

overriding
function Is_Happy (Ptr : access Cat_t) return Boolean;

if you want the compiler to check that it really is overriding).

By the way, if you are using Ada 2005 or later you can use the prefixed notation to write the calls as

Animal_Ref.Stroke_Fur;
Result := Animal_Ref.Is_Happy;

which is prettier.



来源:https://stackoverflow.com/questions/35898525/dynamic-dispatching-in-ada-with-access-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!