【问题标题】:Derived class does not call base class method派生类不调用基类方法
【发布时间】:2016-01-01 20:31:17
【问题描述】:
class MyBaseClass
{
  virtual public void Print()
    {
      Console.WriteLine("This is the base class.");
    }
}

class MyDerivedClass : MyBaseClass
{
  override public void Print()
   {
     Console.WriteLine("This is the derived class.");
   }
 }

class Program
  {
    static void Main()
    {
      MyDerivedClass derived = new MyDerivedClass();
      MyBaseClass mybc = (MyBaseClass)derived;

      derived.Print();
      mybc.Print();

    }
   }

输出:

This is the derived class.
This is the derived class.

我不明白为什么第二次调用会打印派生类的 print() 方法,因为我将 mybc 对象转换为基类。我希望它改为打印基类打印方法。我在这里遗漏了什么吗?

【问题讨论】:

  • 查看此网站上的类似问题以进行深思熟虑的讨论:stackoverflow.com/questions/1334254/…
  • 删除 override 关键字,一切正常
  • @PranavPatel 从技术上讲它可以工作,但通常这是一个糟糕的设计。

标签: c# inheritance derived-class base-class


【解决方案1】:

变量类型和实例类型是两种不同的类型。强制转换不会更改实例类型。

当您将方法声明为虚拟/抽象时,您是在说您想要 实例类型以确定调用时的行为。

还要注意,这个赋值是有效的——不需要转换语法来将变量类型从子类更改为基类。这种类型的转换可以隐式完成。

MyBaseClass mybc = derived;

【讨论】:

  • 小心 c# 转换语法,它有时会转换,有时会转换。
  • 当我将派生对象转换为基础对象时,就像上面的代码一样,我是否更改对象类型?例如,在这段代码中,mybc 变成了 MyBaseClass 对象,还是只是指向派生对象的指针? MyBaseClass mybc = (MyBaseClass) 派生的;
  • 你没有。你是说:“使用这个 Shape 变量来引用我的 Square”,但它仍然是一个 Square。
  • 请纠正我。我创建了一个指向基类对象的指针,这个指针(“mybc”)得到了一个派生类对象的地址,该派生类对象被显式地转换为它的基类。现在 mybc 指向什么?派生对象还是基础对象? (我有 C 背景,所以很难理解这个概念)
  • mybc 是一个引用 MyDerivedClass 实例的变量。不要混淆铸造和转换。转换生成指定类型的新实例。强制转换告诉编译器这个引用指向那个实例是可以的。
【解决方案2】:

你已经覆盖了它。它只调用派生方法。你必须明确call the base class' method:

override public void Print() {
     base.Print();
     Console.WriteLine("This is the derived class.");
}

【讨论】:

  • 当然,您只能从覆盖类内部调用基本版本。你不能从类外调用基础版本。
【解决方案3】:

重写虚方法的全部意义在于调用对象底层(运行时)类型的版本,而不是静态(编译时)类型的版本——即使您通过声明的类型调用它作为基类。

所以这完全符合它应该的行为。

如果不是这种情况,它会使类层次结构的许多实用程序变得无用,因为您无法通过将自定义派生类传递给方法来更改传递给方法的类类型的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2014-09-05
    • 2011-05-11
    • 2016-07-06
    • 2014-02-15
    • 2013-03-28
    • 2013-04-11
    相关资源
    最近更新 更多