首页 新闻 会员 周边 捐助

一个关于重载的问题

0
[已解决问题] 解决于 2013-01-22 13:50

无意间看到这个问题

 class a
    {
        public void show()
        {
            Console.WriteLine("这是无参方法");
        }

    }

    class b : a
    {
        //这个方法算是重载么?
        public void show(int num)
        {
            Console.WriteLine("这是有参方法,参数是:"+num);
        }
    }

这个问题以前也是非常迷惑的,我是这样想的,所谓继承其实就是编译器把父类可以被继承的东西复制到子类中去,所以上面的class b实际上是在编译期间被编译成这样的

class b 
    {
        public void show()
        {
            Console.WriteLine("这是无参方法");
        }
        //这个方法算是重载么?
        public void show(int num)
        {
            Console.WriteLine("这是有参方法,参数是:"+num);
        }

 

}

(我只是这么个意思,当然不可能编译成这样的代码),所以这种情况也是重载。不知道我的理解对不对,求指正呢

C#
动感超人z的主页 动感超人z | 初学一级 | 园豆:1
提问于:2013-01-21 20:36
< >
分享
最佳答案
0

你的例子不应该是重载,因为两个show函数的范围不同(不在同一个类中)。

编译器也不会像你那样来处理,因为继承的原因,访问 void show() 的方式是通过父类来实现的。也就是说编译后 b 的函数表不会包含 void show() 方法;void show() 方法只会存在于 a 的函数表中。b 通过父类 a 的函数表来调用 void show() 方法。

奖励园豆:5
Launcher | 高人七级 |园豆:45050 | 2013-01-22 09:25

据我所知类是有一个叫方法列表的东西吧,所谓继承编译器会去父类的方法列表中拷贝所有可继承的方法然后放到子类的方法列表中,而这一切都是在编译期间完成的。到运行时会给方法列表中的每一个方法添加方法指针(网上查到的加上自己分析,要是有哪里不对,请指出)

动感超人z | 园豆:1 (初学一级) | 2013-01-22 12:11

好吧,我用反汇编看了一下

   static void Main()
        {
            var b = new b();
            b.show();

        }

这段代码反汇编是这样的结果,确实执行的是class a中的show

结合Qlin的回答

这种情况实际上类似与下面这样

  class b
    {
       public a a=new a();
            //这个方法算是重载么?
        public void show(int num)
        {
            Console.WriteLine("这是有参方法,参数是:" + num);
        }
    }
//当调用的时候,类似于这样
 static void Main()
        {
            var b = new b();
            b.a.show();

        }

不知这样是否是对的?

动感超人z | 园豆:1 (初学一级) | 2013-01-22 13:00

@枼秋: 大概就是这个意思,由于文章较长,这里有篇实际分析的文章:

http://www.itstrike.cn/Question/CLR-how-to-achieve-polymorphic-virtual-method-calls-I

其中也提到对几个问题的分析:

  • Base类中的所有虚方法在Derived类的Method Table中一一对应
  • Base类中的所有非虚方法在Derived类中的Method Table并没有拷贝(这一点回答了上面的第一个问题)
  • Derived类新增的虚方法都添加到继承自Base类的虚方法的后面
  • 如果Derived类override Base类的虚方法,它就将该方法指向自身的实现
  • 如果Derived类使用new关键字隐藏了Base类虚方法的实现,它就相当于增加了一个虚方法,而不是覆盖。
Launcher | 园豆:45050 (高人七级) | 2013-01-22 13:43
其他回答(3)
0

当然是 重载,理解  b对象的内存分配 就不会有这个疑问了。

Qlin | 园豆:2403 (老鸟四级) | 2013-01-22 09:02

class a在栈上有自己的方法列表,class b在栈上也有自己的方法列表,编译器会去class a中的把方法列表中可以继承的方法拷贝到class b 中。等到运行时(new 的时候)会为方法列表的方法分配自己的指针。我认为内存中应该是这样的,is that?

支持(0) 反对(0) 动感超人z | 园豆:1 (初学一级) | 2013-01-22 12:17

@枼秋: 

不是在 栈上,在堆上。 原来我也是这样认为,看了 Launcher 大哥的回答,我开始怀疑了。

支持(0) 反对(0) Qlin | 园豆:2403 (老鸟四级) | 2013-01-22 12:26

@Qlin: 

不知我们的理解是不是一样的,帮忙看一下吧  我对 Launcher 大哥的回答

支持(0) 反对(0) 动感超人z | 园豆:1 (初学一级) | 2013-01-22 13:02
0

应该算是吧,但是你这样的写法,很让人感到困惑。

chenping2008 | 园豆:9836 (大侠五级) | 2013-01-22 09:14

可否说的详细点?是我的想法不对么?

支持(0) 反对(0) 动感超人z | 园豆:1 (初学一级) | 2013-01-22 12:00
0

是重载,重载就是说两个方法名字相同了,但签名不同,这两个方法没有啥联系。所以,这果断就是两个名字一样,但没任何关联的方法,那自然是重载

那编译器处理时,就是b继承了a中的public方法和protect方法,所以show()和show(int num) 两个方法都在,而且这两个方法没啥关系,只不过是名字一样,使用时,会根据参数的不同来智能识别。

指尖的乐律 | 园豆:237 (菜鸟二级) | 2013-01-22 11:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册