Consider following C++ code:

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

void Dinner(Person & ModifyPerson)
{
    ModifyPerson.Weight += 2;
}


名称是常量,创建人员时首先对其进行初始化。
重量是可修改的。

Person Person0("Conny");
Dinner(Person0);


让我们在Ada中尝试一下:

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

Person0 : Person := Person'(Name => "Abby");


人员的名称应始终为“ Abby”,因为其常数和权重应可修改且0为默认值。

无法使用,因为Ada记录不允许以下操作:


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


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

在C ++中,我可以通过派生扩展Person。
在Ada中,我们为此使用带标签的记录。
但是带标签的记录也不起作用。

如何使用具有扩展功能的Person的Ada代码编写C ++代码?

最佳答案

在Ada中,您首先要确定Person可以做什么和不能做什么,然后设计接口。该实现稍后发布。

据我从您的班级看到,您希望一个人:


名称不可变(婚姻可能是个问题,但没关系)
重量可变,初始化为0
有增重或减肥的能力。
通过讨论,可以扩展(可细分)


现在,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;


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

私有部分包含类型声明的详细信息,因此客户端代码可以为Person分配空间,而基本上没有其他原因。因此,除了公共接口外,您还无需摆弄记录字段……我认为我不需要阐明为什么这是一件好事吗?所以私有部分看起来像

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


这是一个有区别的记录,因此我们可以将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;


用法(另存为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;


编译:

gcc -c -gnat2012 main.adb
gcc -c -gnat2012 person_pack.adb
gnatbind -x main.ali; gnatlink main.ali

关于c++ - Ada记录缺少的功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27382575/

10-13 04:27