none
关于方法表和虚方法的问题! RRS feed

  • 问题

  • 问题1:子类型的方法表是否包含了父类型的方法。

    问题2:虚方法多态的调用  怎么样从方法表或其它方面进行解释。

    本人没有找到权威的解释 所以在此请教各位 抱拳先谢过

    2011年1月22日 7:49

答案

  • 您好,

    1、子类型的方法表里没有包含父类型的方法。当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。

    2、CLR会判断具体实例化的类的类型(子类)而不是判断声明时的类的类型(父类),并从方法表中找到匹配的方法。在方法表中,包含了父类的基方法和子类的重写方法。

    提供一个查看元数据的工具CFF Exploer。下载地址:http://www.ntcore.com/files/ExplorerSuite.exe

    用该工具配合《CLR via C#》第3版的第2章 2.3 元数据概述。也可参考《.NET加密与解密》的第3章。

     

    • 已标记为答案 刘汉威 2011年1月27日 3:03
    2011年1月22日 12:53
    版主

全部回复

  • 您好,

    1、子类型的方法表里没有包含父类型的方法。当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。

    2、CLR会判断具体实例化的类的类型(子类)而不是判断声明时的类的类型(父类),并从方法表中找到匹配的方法。在方法表中,包含了父类的基方法和子类的重写方法。

    提供一个查看元数据的工具CFF Exploer。下载地址:http://www.ntcore.com/files/ExplorerSuite.exe

    用该工具配合《CLR via C#》第3版的第2章 2.3 元数据概述。也可参考《.NET加密与解密》的第3章。

     

    • 已标记为答案 刘汉威 2011年1月27日 3:03
    2011年1月22日 12:53
    版主
  • dear
    1.子类别可以拥有父类别的所有方法,除了private方法外
    2.当子类别有方法与父类别相同,VS会有警告提示,若要解除警告有两种做法,一是在子类别方法中使用New关键字,二是在父类别使用virtual,子类别用override,这样就可解决警告提示。被覆写过的方法,仍可被呼叫,这时可以使用base关键字来呼叫未被复写的方法

    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年1月23日 9:21
  • hi, 楼上两位MVP,我想你们是否把楼主想的太简单了?如果是这些基础的面向对象的知识,我想楼主应该不会说出“方法表”这个概念,这个不是初学者能提出的。所以我想楼主应该是在c#上有一定造诣了,想更深入地研究一下后面的工作原理。

    所以我上面提到的“子类型的方法表里没有包含父类型的方法。当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。”这个就是"权威"的答案。啥,我是谁?我算哪根葱?哦,对不起,"当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。"这句不是我说的,是Jeffrey Richter说的。那“子类型的方法表里没有包含父类型的方法。”(我这里是指子类没有重写父类的方法,下面会提到有重写的情况)这句呢?对不起,我不知道有谁说过,这是我个人从元数据中看到的,元数据应该够权威吧。啥?我看的有问题,那好,您也可以通过CFF来看。因为元数据中方法表只有一个,更准确的说,是方法表中没有一个方法被子类型引用。但这不代表子类中不继承基类的方法,刚才谈到了,子类中没有的方法,会尝试从基类中调用。一个是从元数据的角度来看问题,一个是从面向对象的语法来看问题。一个代表后台的工作机理,一个是表象便于程序员理解。

    关于第二点,如果基类中有virtual方法,子类中又override了这个方法,那么在方法表中有两个方法,一个被基类引用,一个被子类引用。更多的信息,我说了不算,可以自己写一个简单的继承关系的类,编译后,用CFF一看便明白。有很多组合,可自行总结。

    hi 楼主,楼主......喂 楼主,我是否理解对了你的意思呢?人呢?唉,不知又去哪潜水了。这个论坛有几个有意思的地方:

    1、经常提问者提问后,便不见踪影。搞得答题者比提问者更积极。

    2、答题者的积极是有限的,毕竟除了微软员工,应该没人领微软工资,所以没有物质鼓励,应有精神鼓励,可惜很多(不是全部)提问者都是不太愿意标记答案或者投票,即使你的答案是正确的或是有帮助的。他们都一概不理。因此严重打击积极性。因此经常看到新人说答题太慢,这是恶性循环啊。这个现象在国内外l微软论坛都有。

    我想是否跟没有一个激励机制有关呢?光靠微软员工和版主应该是不行的,人气上不去啊。

    唉,说多了,楼主不好意思,新年之际,借贵地调侃了,祝你和大家新春愉快!兔年大吉!

     

    2011年1月26日 7:09
    版主
  • 没仔细阅读,你理解的是对的。删除我那段了,免得误导。
    我去温习下 CLR via C#


    2011 c# mvp China
    2011年1月26日 8:18
    版主
  • Hi George,

    您好,不好意思,多谢您的认同。

    2011年1月26日 13:23
    版主
  • <pre lang="x-c#">
    internal class a { internal virtual void helloWorld() { Console.WriteLine("aaaaaaaaaaa............"); } } internal class b : a { override internal void helloWorld() { Console.WriteLine("bbbbbbbbbbbbbbb............"); } } internal class c : b { new internal virtual void helloWorld() { Console.WriteLine("ccccccccccccccc............"); } } class Program { static void Main(string[] args) { a A = new b(); //发现A 实际类型是B 则在B的方法表里找helloWorld方法 //发现是A实际调用的方法则指向A.helloWord //发现B将方法重写则调用B.helloWorld //若B没有重写则会调用A.helloWorld A.helloWorld(); A = new c(); //同上 因为不存在override的方法又被其子类override A.helloWorld(); Console.ReadKey(); } }

    见谅见谅 这个是我的错 跟大家拜个早年

    关于静态和实例方法调用的时候很好理解
    直接在调用类的方法表里面找 如果没有就在父类找

    关于虚方法 多态的调用

    会找到调用对象指针的实际类型 然后指向调用对象的方法(而不是实际类型的方法)

    不知道我理解的对不对 望指教!

    2011年1月26日 13:29
  • 哈,楼主,您好。

    和我理解的差不多,这里“(而不是实际类型的方法)”是笔误吧,应该是:而不是声明类型的方法。

    2011年1月26日 13:57
    版主
  • 关于第二点,如果基类中有virtual方法,子类中又override了这个方法,那么在方法表中有两个方法,一个被基类引用,一个被子类引用。

    a A = new b();
       //发现A 实际类型是B 则在B的方法表里找helloWorld方法
      //发现是A实际调用的方法则指向A.helloWord
      //发现B将方法重写则调用B.helloWorld
       //若B没有重写则会调用A.helloWorld
       A.helloWorld();

     

    这里我理解的是 应该调用的是实际类型(b)方法表中指向基类的那个方法(a.helloWorld)
    始终会调这个方法 只不过如果b将a的虚方法重写后改变了a.helloWorld的表现形式

    2011年1月26日 15:08
  • 这个时候实际类型b中有自己的方法(override),无需指向基类。正如我上面提到的,此时父类和子类都有属于自己的相同签名的方法。您可以用CFF看一下。有空的时候我写个文章,贴个图就清楚了。
    2011年1月27日 1:40
    版主
  • OK!!!
    2011年1月27日 3:02
  • 看了你的回复,决定无论如何都要支持你一把!必须的。
    2011年4月13日 14:31
  • hi, 楼上两位MVP,我想你们是否把楼主想的太简单了?如果是这些基础的面向对象的知识,我想楼主应该不会说出“方法表”这个概念,这个不是初学者能提出的。所以我想楼主应该是在c#上有一定造诣了,想更深入地研究一下后面的工作原理。

    所以我上面提到的“子类型的方法表里没有包含父类型的方法。当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。”这个就是"权威"的答案。啥,我是谁?我算哪根葱?哦,对不起,"当调用某个方法时,CLR用call或callvirt指令来调用,如果没有发现该方法,则会尝试从父类型中查找匹配的方法。"这句不是我说的,是Jeffrey Richter说的。那“子类型的方法表里没有包含父类型的方法。”(我这里是指子类没有重写父类的方法,下面会提到有重写的情况)这句呢?对不起,我不知道有谁说过,这是我个人从元数据中看到的,元数据应该够权威吧。啥?我看的有问题,那好,您也可以通过CFF来看。因为元数据中方法表只有一个,更准确的说,是方法表中没有一个方法被子类型引用。但这不代表子类中不继承基类的方法,刚才谈到了,子类中没有的方法,会尝试从基类中调用。一个是从元数据的角度来看问题,一个是从面向对象的语法来看问题。一个代表后台的工作机理,一个是表象便于程序员理解。

    关于第二点,如果基类中有virtual方法,子类中又override了这个方法,那么在方法表中有两个方法,一个被基类引用,一个被子类引用。更多的信息,我说了不算,可以自己写一个简单的继承关系的类,编译后,用CFF一看便明白。有很多组合,可自行总结。

    hi 楼主,楼主......喂 楼主,我是否理解对了你的意思呢?人呢?唉,不知又去哪潜水了。这个论坛有几个有意思的地方:

    1、经常提问者提问后,便不见踪影。搞得答题者比提问者更积极。

    2、答题者的积极是有限的,毕竟除了微软员工,应该没人领微软工资,所以没有物质鼓励,应有精神鼓励,可惜很多(不是全部)提问者都是不太愿意标记答案或者投票,即使你的答案是正确的或是有帮助的。他们都一概不理。因此严重打击积极性。因此经常看到新人说答题太慢,这是恶性循环啊。这个现象在国内外l微软论坛都有。

    我想是否跟没有一个激励机制有关呢?光靠微软员工和版主应该是不行的,人气上不去啊。

    唉,说多了,楼主不好意思,新年之际,借贵地调侃了,祝你和大家新春愉快!兔年大吉!

     

    我是要支持你!
    2011年4月13日 14:38
  • 不包含

    一样


    胡超
    2011年4月13日 17:33
  • hi _qiaohe_,

       谢谢你的支持!:)

       最近公司忙,来论坛的时间少了。

    2011年4月14日 11:38
    版主
  • 子类型的方法表应该包含有父类型的方法吧~如果了、父类型的方法为private是不可调用。但是子类型的方法表中应该包含父类这个方法

    是这样的吗?


    Ellis_Wong
    2011年4月14日 12:44