我有一个基本类型,其工作是维护项目列表。 它具有非调度功能,可以向其中添加项目以及从中检索项目列表。

从此基本类型派生的类型使用某些调度子程序中的项目。 我已经可以通过使基本类型包含项的向量来实现这一点,但是如果可能的话,我希望数组是静态的。 这是我到目前为止的内容:

bases.ads:

package Bases is
    type Base (<>) is tagged private; -- I want to hide the size
    type Int_List is array (Positive range <>) of Integer; -- as an example

    function Create return Base; -- returns an empty Base

    function Add_To (This : Base'Class; I : Integer) return Base'Class; -- Append
    function Image (This : Base) return String; -- Dispatching example
    function List (This : Base'Class) return Int_List; -- Get the data for internal use
private
    type Base (Size : Natural) is tagged record
        Ints : Int_List (1 .. Size);
    end record;
end Bases;

bases.adb:

package body Bases is
    function Create return Base is (Size => 0, Ints => (others => 0));
    function Add_To (This : Base'Class; I : Integer) return Base'Class is
        -- This is where I have trouble: "aggregate cannot be of a class-wide type"
        Copy : Base'Class := (This with Size => This.Size + 1, Ints => This.Ints & I);
    begin
        return Copy;
    end Add_To;
    function Image (This : Base) return String is ("BASE");
    function List (This : Base'Class) return Int_List is (This.Ints);
end Bases;

派生广告:

with Bases;
package Deriveds is
    type Derived is new Bases.Base with null record;
    function Create return Derived;
    function Image (This : Derived) return String;
end Deriveds;

派生的.adb:

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package body Deriveds is
    function Create return Derived is (Bases.Create with null record);
    function Image (This : Derived) return String is
        Result : Unbounded_String;
        Ints : Bases.Int_List := This.List;
    begin
        for I in Ints'Range loop
            Result := Result & Integer'Image (Ints (I));
        end loop;

        return To_String (Result);
    end Image;
end Deriveds;

同样,我知道,如果我只是删除判别式并使用受控类型来存储数组,则可以将副本创建为Copy : Base'Class := This; 并在返回之前对其进行变异。 但是,我觉得应该只有静态内存才可以做到这一点,这是可取的。 我唯一想到的其他解决方法是创建另一个带标签的类型,该类型将是包含列表和Base'Class数据的记录,并且其操作将Base'Class Base调度操作,并使其通过。

有没有办法在Add_To创建Copy ,使它的判别式大1,并且只使用静态内存添加一个额外的元素?

#1楼 票数:1

我认为麻烦在于, Bases.Add_To没有令人愉快的标准方法来知道要追加到Base记录(随Size增加)以复制This实际的特定于类的数据。

我想您可以不受限制地转换并通过使用Ada.Tags.Generic_Dispatching_Constructor在这里在此处 )来构造记录; 但似乎是个坏主意。

#2楼 票数:1

我知道这需要更多的工作,但是您也可以将Add_To更改为使用Base而不是Base'Class。 然后,您必须为具有大于null记录扩展名的所有派生类型重写它,但是您将获得所需的静态数组结果。 派生的实现将类似于您实现Create的方式。

示例(我将派生类修改为具有非null记录扩展名,以强制编译器要求您派生该操作:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Hello is

    package Bases is
        type Base (<>) is tagged private; -- I want to hide the size
        type Int_List is array (Positive range <>) of Integer; -- as an example

        function Create return Base; -- returns an empty Base

        function Add_To (This : Base; I : Integer) return Base; -- Append
        function Image (This : Base) return String; -- Dispatching example
        function List (This : Base'Class) return Int_List; -- Get the data for internal use
    private
        type Base (Size : Natural) is tagged record
            Ints : Int_List (1 .. Size);
        end record;
    end Bases;

    package body Bases is
        function Create return Base is (Size => 0, Ints => (others => 0));
        function Add_To (This : Base; I : Integer) return Base is
            -- This is where I have trouble: "aggregate cannot be of a class-wide type"
            Copy : Base := (Size => This.Size + 1, Ints => This.Ints & I);
        begin
            return Copy;
        end Add_To;
        function Image (This : Base) return String is ("BASE");
        function List (This : Base'Class) return Int_List is (This.Ints);
    end Bases;

    package Deriveds is
        type Derived is new Bases.Base with  record
            Value : Integer;
        end record;
        function Create return Derived;
        function Add_To(This : Derived; I : Integer) return Derived;
        function Image (This : Derived) return String;
    end Deriveds;

    package body Deriveds is
        function Create return Derived is (Bases.Create with Value => 0);
        function Image (This : Derived) return String is
            Result : Unbounded_String;
            Ints : Bases.Int_List := This.List;
        begin
            for I in Ints'Range loop
                Result := Result & Integer'Image (Ints (I));
            end loop;

            return To_String (Result);
        end Image;
        function Add_To(This : Derived; I : Integer) return Derived is
        begin
            return (Bases.Base(This).Add_To(I) with Value => This.Value);
        end Add_To;
    end Deriveds;

    use Deriveds;

    d0 : Derived := Create;
    d1 : Derived := d0.Add_To(1).Add_To(3);
    d2 : Derived := d1.Add_To(2);

begin
  Put_Line(d2.Image);
end Hello;

  ask by LambdaBeta translate from so

未解决问题?本站智能推荐:

2回复

Ada-如何初始化包含File_Type成员的有限标记类型?

在下面的代码中,Mix_Card_Reader 继承自 Mix_IO_Device,后者是一个抽象的标记记录。 以前它包含一个Positive和两个Stream_Access成员。 我想更改代码,以便它使用File_Type成员。 这样做的原因是我希望这种类型的每个实例都能够在需要时打开和关闭其文件
1回复

使用Ada的My_Class'Class(This)强制模仿模板方法设计模式

语境 我最近遇到了一个基本的OOP / Ada 2012设计问题。 基本上,我有一个实现接口协定的父类。 这是在实现提供程序(ConcreteX)中分几个步骤完成的。 子类通过仅覆盖其中一个步骤(DerivedY,Step_2)来扩展此实现。 (试图获得一些SOLID属性) 我
4回复

如何访问对象内的对象?

我正在尝试制作二十一点游戏。 我已经创建了一个牌组,现在我想显示它。 我知道我做错了,因为我无法访问CardStack类中的displayStack。 另外,我有一种感觉,我没有正确进行继承。 我该如何解决? 这是我的代码: 卡类: CardStack类: 主类:
3回复

覆盖将类范围的类型作为Ada中的参数接收的过程

我试图了解Ada中面向对象的工作方式。 我发现无法解决的情况。 我知道如何使用类范围的类型来启用多态性,并且我知道如何从派生类中重写父类的方法。 我不知道该怎么做,是重写一个将类宽类型作为参数的过程,因为我总是会遇到编译错误。 我在下面对此进行深入解释: 我尝试过的 类型1
1回复

在Ada95中实现具有类范围操作的接口

我正在使用Ada 95创建程序,但遇到了问题。 具体来说,我正在尝试实现一个类,该类执行作为参数给出的仿函数。 我要实现的行为是: 用过程Execute声明接口IF 。 从IF派生C类并实现Execute 。 创建一个类D ,该类的字段是IF数组。 由于无法实例化IF
2回复

从Ada中的基类调用重写方法

我想知道如何从ADA中的父类调用重写方法。 让我们考虑以下示例。 Parent类有一些被Child类重写的方法。 Parent类中有一个方法(即Prints )调用它的一些重写方法。 但是被覆盖的方法没有被调用! 这是一个例子: ---父母--- ---孩子--- ---主
1回复

在Ada中,如何将constraint_error更改为自定义异常?

我正在使用链表堆栈,并且希望它出现下溢错误,因此我可以看到它正常运行。 但是,它一直给我一个约束错误消息,我想在其中出现下溢消息。 关于该怎么做的任何提示都将有所帮助。 由于服务器已关闭,我目前无法输入代码,但我会尽快更新
3回复

堆栈上的可执行Ada代码

我刚刚从去年的32C3开始 就铁路系统的安全考虑进行了讨论。 在第25分钟,演讲者简要介绍了阿达。 他具体说: 典型的Ada实现具有称为“(tramp / trunk /?)行”的机制。 这意味着它将在[堆栈]上执行代码,这对C程序来说并不是很好。 [...]如果您想将Ada代码与