缺少Ada记录的功能

Jos*_*ssi 0 c++ initialization constants record ada

考虑遵循C++代码:

class Person
{
public:
    const std::string Name;
    int Weight = 0;
    Person(std::string AssignName) : Name(AssignName)
    {}
};

void Dinner(Person & ModifyPerson)
{
    ModifyPerson.Weight += 2;
}
Run Code Online (Sandbox Code Playgroud)

名称是常量,并且在创建Person时首先初始化.重量可以修改.

Person Person0("Conny");
Dinner(Person0);
Run Code Online (Sandbox Code Playgroud)

让我们在Ada中试试这个:

type Person is record
    Name : constant String;
    Weight : Integer := 0;
end record;

Person0 : Person := Person'(Name => "Abby");
Run Code Online (Sandbox Code Playgroud)

的名字应该永远是'艾比’,因为它常和重量应该是修改和0作为defualt.

不起作用,因为Ada记录不允许以下内容:

  • 恒定场
  • 字段类型的未指定范围
  • 限制初始化列表,即仅分配名称,并且权 = 0作为默认值.

如何在Ada代码中执行C++代码?

在C++中,我可以通过派生来扩展Person.在Ada中,我们使用标记记录.但标记记录也不起作用.

如何使用Person的可扩展功能在Ada代码中执行C++代码?

Bri*_*ond 7

在Ada中,您首先要确定Person可以做什么,不能做什么,然后设计界面.稍后实施.

据我所见,你想要一个人:

  1. 有一个不变的名字(婚姻可能是一个问题,但没关系)
  2. 有一个可变的重量,初始化为0
  3. 有能力减肥或减肥.
  4. 从讨论开始,可扩展(可子类化)

现在Ada记录就像一个Struct,但是我们想要的不仅仅是那个,并且将数据类型及其操作包装在一起的通常方法是Package.(这也与C++命名空间有一些共性,它也使主命名空间保持整洁)

Package Person_Pack is
  -- tagged for extensibility and other goodies
  type Person (Name_Length : Natural) is tagged private;
  function Name (P:Person) return String;
  function Weight (P:Person) return Natural;
  procedure Gain_Weight (P: in out Person; Increment : Integer);
  -- Explicit constructor, like "object factory" pattern
  function Birth(Name : String) return Person;
private
  -- none of your business yet...
end Person_Pack;
Run Code Online (Sandbox Code Playgroud)

这就是界面(将其保存为"person_pack.ads").有一个getter方法但没有Name的setter方法,我们保证了它Person.Name的恒定性.

私有部分包含类型声明的详细信息,以便客户端代码可以为a分配空间Person,基本上没有其他原因.所以,除了公共界面之外,没有摆弄记录字段...我不认为我需要说明为什么这是一件好事?所以私人部分可能看起来像

private
  type Person (Name_Length : Natural) is tagged record
    Name   : String(1 .. Name_Length);
    Weight : Integer := 0;
  end record;
end Person_Pack;
Run Code Online (Sandbox Code Playgroud)

这是一个有区别的记录,因此我们可以直接将Name存储在记录中,而不是使用Ada.Containers(最接近于STL),甚至是Unbounded_String.这是一个实现细节,因为它仅限于私有部分,如果我们稍后更改它而不更改接口,并重新编译,客户端代码仍然有效.

实现在包体中,"person_pack.adb".

Package Body Person_Pack is
  function Name (P:Person) return String is
  begin
    return P.Name;
  end Name;

  function Weight (P:Person) return Natural is
  begin
    return P.Weight;
  end Weight;

  procedure Gain_Weight (P: in out Person; Increment : Integer) is
  begin
    P.Weight := P.Weight + Increment;
  end Gain_Weight;

  function Birth(Name : String) return Person is
    baby : Person(Name'Length);
  begin
    baby.Name := Name;
    baby.Weight := 0;
    return baby;
  end Birth;

end Person_Pack;
Run Code Online (Sandbox Code Playgroud)

用法(另存为main.adb):

with Person_Pack; use Person_Pack;

procedure Main is

  -- type extension : refactor this into another package...
  type Employee is new Person with
    record
      Salary : Integer;
    end record;

  function Birth(Name : String) return Employee is
    baby : Person(Name'Length) := Birth(Name);
  begin
    return (baby with Salary => 0);
  end Birth;

  Abby : Person := Birth("Abigail");
  John : Employee := Birth("John");

  procedure Dinner (Gourmand : in out Person) is
  begin
    Gourmand.Gain_Weight(2);
  end Dinner;

begin
  Dinner(Abby);
end Main;
Run Code Online (Sandbox Code Playgroud)

编译:

gcc -c -gnat2012 main.adb
gcc -c -gnat2012 person_pack.adb
gnatbind -x main.ali; gnatlink main.ali
Run Code Online (Sandbox Code Playgroud)


ajb*_*ajb 5

公共数据成员对任何面向对象的语言都不满意.因此,即使在C++中,我希望具有扎实设计背景的人能够告诉您放入NameWeight放入该private:部分,并添加getter和setter方法来检索和设置字段.当然你不会有一个setter Name因为它是不可更改的.

Ada也一样.使record私有:

    type Person is private;  --or
    type Person is tagged private;

    function Make_Person (Name : String; Weight : Integer := 0) return Person;

    function Get_Name (X : Person) return String;

    function Get_Weight (X : Person) return Integer;
    procedure Set_Weight (X : in out Person; Weight : Integer);

private

    type Person is record --or
    type Person is tagged record 
        Name : Ada.Strings.Unbounded.Unbounded_String;
        Weight : Integer;
    end record;
Run Code Online (Sandbox Code Playgroud)

Unbounded_String是处理字符串变量或记录字段长度可以动态更改的常用方法.有关如何使用此软件包以及如何在类型和类型之间进行转换的信息,请参阅RM A.4.5.这些转换只会出现在定义的包的主体中; 使用它的客户端包不必担心它.Unbounded_StringStringPersonPerson

如果你创建Person了一个tagged record,你仍然可以使用"点"表示法来访问这些函数:

P : Person;

...

Name : String := P.Get_Name;       -- calls the getter function
Weight : Integer := P.Get_Weight;  -- calls the getter function

P.Set_Weight (P.Get_Weight + 2);
Run Code Online (Sandbox Code Playgroud)

我不能回应你的陈述"标记记录也不起作用",因为你没有提供任何细节.