如何调用子类型上的函数?

时间:2016-12-22 18:52:05

标签: c++ polymorphism language-design subtyping

我目前正在设计一种编程语言,我很想知道如何解决这个问题:

假设我有一个看起来像这样的类(或接口):

class A { // size is 4 bytes
  int32 a = 0;
}

和扩展它的第二个B类看起来像这样:

class B extends A { // size is 8 bytes
  int32 b = 0;
}

我有一个看起来像这样的函数f:

int32 f(A first, A second) {
  return first.a + second.a;
}

但是,如果我用两个B调用它,则second.a不会在同一个位置,就像用两个As调用它一样,因为第一个参数会移动它。我目前解决这个问题的想法是:

  1. 禁止使用未知大小的参数,并强制将其作为指针或引用传递(我认为这就是Rust所做的)
  2. 将以下所有信息写入调用堆栈:指向第二个指针,指向第二个指针,非可变大小参数,第一个,第二个
  3. 为第一个和第二个的每个可能大小创建一个函数,并确定在编译时调用哪个函数,如果已知,或在运行时使用vtables。
  4. 第二个想法是一个问题,因为它需要得到所有函数的支持,即使它们很少或从不使用子类型调用,这是低效的。

    第三个想法需要创建很多函数(一个接受5个参数的函数,它可以是20个不同的子类型,需要生成100个相似的代码片段,如果它只被称为一个具有未知类型的参数),并且每个只有一个功能使用它的类需要一个vtable。此外,已编译库中的函数不能与新子类型一起使用。

    组合2和3并创建相同函数的两个版本,一个只接受类型,另一个接受子类型也可以解决其中的一些问题。

    我很好奇是否有更好的解决方案,以及C ++等其他语言如何实现这一点。

1 个答案:

答案 0 :(得分:3)

在C ++中,使用子类型f(A)的参数按值调用B等同于

f(static_cast<const A&>(b));

static_cast可能导致同一地址的内存被重新解释为较短数据块的开头,或者先透明地添加一些偏移(如果A不是第一个基类或者是虚拟的)。之后,在内部,调用A的复制构造函数。在任何一种情况下,B添加的信息都会完全丢失,同时还会覆盖虚函数。出于所有目的,传递的内容不再是B

动态多态性需要引用或指针,这很大程度上是出于您概述的原因。但是,如果您想通过值&#34;传递&#34;引用,最简单的解决方案可能是将引用传递给对象的副本。请注意,在这种情况下,每个对象都需要知道&#34;调用正确的拷贝构造函数是什么类型,或者从公共超类派生并实现某种形式的clone()

相关问题