静态绑定期间C ++和Ada的差异

时间:2013-11-16 23:42:04

标签: c# c++ binding ada

我正处于工作的中间,我遇到了这个问题:

  

假设我们有时需要静态绑定,您更喜欢逐个方法吗?   C ++和C#的方法,或Ada 95的变量变量方法?为什么?

我搜索了在线和教科书,但我找不到C ++中逐个方法的方法或Ada中的逐个变量方法的含义。任何人都可以告诉我这些术语的含义,这两种方法更好。

提前致谢!

1 个答案:

答案 0 :(得分:2)

让我们先来看一个例子,C ++:

class Base {
public:
    void a();
    virtual void b();
};

class Derived : public Base {
public:
    void a();
    virtual void b();
};

Base* base = new Base();
Derived* derived = new Derived();
Base* upcastedDerived = new Derived();

base->a(); // calls Base::a()
base->b(); // calls Base::b()

derived->a(); // calls Derived::a()
derived->b(); // calls Derived::b()

upcastedDerived->a(); // calls Base::a()
upcastedDerived->b(); // calls Derived::b()

调用basederived的方法会产生明显的结果。在upcastedDerived上,对a()的调用在编译时绑定(静态绑定),因此它绑定到Base::a(),因为该变量的类型为Base*。但是,对b()的调用在运行时绑定,因为该方法声明为virtual。因为该对象实际上是类Derived,所以Derived::b()被调用。

如您所见,在C ++中,它取决于方法声明方法调用是静态绑定还是动态绑定。请注意,派生类中的关键字virtual是可选的 - 该方法是自动虚拟的,因为它覆盖的基本方法是虚拟的。

现在让我们与Ada做类似的事情:

procedure Dispatching is
   type Base is tagged null record;

   procedure A (Object : in out Base);

   type Derived is new Base with null record;

   overriding procedure A (Object : in out Derived);

   Base_Var : Base;
   Derived_Var : Derived;
   Upcasted_Var : Base'Class := Derived_Var;
begin
   A (Base_Var); -- calls first A() procedure
   A (Derived_Var); -- calls second A() procedure
   A (Upcasted_Var); -- calls second A() procedure
end Derived;

首先要注意的是:Ada没有与virtual类似的关键字。所有方法都可以静态或动态绑定。如您所见,它取决于对象变量的类型:Base_VarDerived_Var都具有具体类型,因此调用该类型的过程。另一方面,Upcasted_Var具有类范围类型(​​在C ++中没有等价物)。因此,对A()的第三次调用是动态绑定的。

总结一下:C ++(和C#)有一种方法可以注释方法是否应该调度。 Ada有一种方法可以注释一个对象变量是否应调度其函数。要控制是否调用调用,可以将变量转换为Ada中的类范围类型(​​不应该转换为具体类型以防止调度,因为如果已经有类范围类型,你无法确定是否可以施放它。)

你可以这样看:在C ++中,任何指向类的指针类型都是类范围的。在Ada中,标记类型的任何原始子例程都是虚拟的。为了完整起见,以下是如何根据C ++中的变量阻止调度:

upcastedDerived.Base::b();

我不会讨论哪些是更好的方法,因为这主要是基于意见的。