自定义访问继承的函数

时间:2012-03-25 15:52:11

标签: c# java c++ oop

使用C#,java或c ++ ...

我们有以下课程

class A
{
  void x(){y();}
  void y(){}
}

class B :A
{
   void y(){};
   void a(){x();}
}

//in main or somewhere 
B b=new B();
b.a();

当调用函数“a”时,它将调用基数“x”函数 问题是,函数“x”将调用哪个函数(基数y()/派生y())? 我们如何控制哪一个调用!!

注意:采取这个概念,我知道三种语言不一样。

3 个答案:

答案 0 :(得分:2)

(假设您打算将所有内容声明为公共内容,并为每种语言使用适当的语法)

在Java和C#中,它将调用B :: y。

在C ++中,它将调用A :: y。

在C ++中,如果您将A :: y声明为虚拟,则会调用B :: y。

实现静态分派(A :: y)比动态分派(B :: y)更高效,因此该选项在C ++中保持打开状态,以便在它们之间进行选择(虚拟或非虚拟)。对于Java和C#,语言设计者决定保持简单,只允许动态调度,因此这两种语言无法进行静态调度(A :: y)。

答案 1 :(得分:2)

您的代码无效C ++,但如果您说B * b = new B; b->a();,则会调用A::y(),因为它不是virtual。在Java中,所有非静态成员函数都是隐式虚拟的,因此在那里调用B::y()

顺便说一下,你的问题非常具有误导性,因为“访问”是完全不同的(与publicprivate等有关)。就此而言,代码不会以任何语言编译,因为B::a()不是public

答案 2 :(得分:2)

此代码示例将执行的操作非常依赖于您在此处使用的语言。你的问题在这里提到了C#/ C ++和Java,它们对于上面的基本模式会有所不同。

C#和C ++在这里非常相似,默认情况下函数不是虚拟的。因此,x()x()的调用将引用A::x。在Java中,虽然默认情况下方法是虚拟的,因此它将引用A::yB::y,具体取决于this的实际类型。

以下是使y()成为虚拟调用的所有3种语言的示例

C ++

class A {
public:
  void x(){ y(); }
  virtual void y(){}
};

class B : public A {
public:
  // virtual not needed here but nice
  virtual void y() { }; 
  void a() { x(); }
};


B* b = new B();
b->a();

C#

class A {
  public void x(){ y(); }
  public virtual void y(){}
}

class B : public A {
  public overrides void y() { }; 
  public void a() { x(); }
};


B b = new B();
b.a();

爪哇

class A {
  public void x(){ y(); }
  public void y(){}
}

class B : inherits A {
  public void y() { }; 
  public void a() { x(); }
};

B b = new B();
b.a();