一道面试题目引发的思考

深入理解对象模型对我们理解面向对象的继承多态会大有裨益。
一直没找到C#这方面的知识,粗浅的看过一点侯捷C++对象模型,实际分析问题的时候发现还是没有深入理解。
无奈到园子里来请教大家。也希望高手前辈能够不吝赐教。如果有意写一些C#对象模型相关的文章我想对于新人来说可谓是莫大的帮助。期待,提前感谢。

你知道下面的代码会输出什么么。
A内部的嵌套类B继承自A

using System;

public class A
{

    
void printA()
    
{
        Console.WriteLine(
"printA");
    }
 
 
public class B : A
    
{
        
new   void printA() // 1
        
{
            Console.WriteLine(
"printB");
        }

    }

    
public static void Main(String[] args)
    
{
        B BTemp 
= new B();
        A ATemp 
= BTemp;

        BTemp.printA();
        ATemp.printA();
        Console.ReadLine();
    }

}

 
上面的代码讲输出
printA
printA
但是在注释1的地方加上public修饰符结果将变成
printB
printA
上网搜了很久参考了下面这篇文章终久还是难解其中之密
http://www.cnblogs.com/caomao/archive/2005/08/16/175459.html  再此感谢Zendy,我很喜欢这篇文章的风格

因为才疏学浅,如果是我少见多怪了。
希望兄弟们善意的提个醒。我好马上从这里撤离,省却在这里丢人现眼。哈哈。

posted on 2007-11-02 09:59 暗香浮动 阅读(1970) 评论(17)  编辑 收藏 所属分类: .net

评论

#1楼  2007-11-02 10:43 GSpring      

我想应该是因为class A和class B中的printA都是private的,那么在Main中是根本看不到class B中的printA方法的,自然就调用不到了
Main是在class A中的,所以可以调用class A中的private方法的   回复  引用  查看    

#2楼  2007-11-02 11:03 rockywu [未注册用户]

很有意思   回复  引用  查看    

#3楼 [楼主] 2007-11-02 11:18 暗香浮动      

@GSpring
默认方法应该是受保护的。btemp又是内部的,所以感觉这里应该可以看到的。

难道是因为A类无法看到B类的方法。只有当B类public的时候才能够被A类看到,才会被覆盖?

关键是我不懂分析的方法。使用IL看了一下。public的时候调用的A/B.printA.
对分析一点用都没有。
谁可以指一条明路告诉我如何去分析呢?
  回复  引用  查看    

#4楼  2007-11-02 11:45 Jeffrey Zhao      

@暗香浮动
编译之后再Reflector出来看,会发现默认方法是private的。   回复  引用  查看    

#5楼  2007-11-02 11:49 学海无涯,回头是岸      

关键字New在作怪

参考http://www.cnblogs.com/allenlooplee/archive/2006/03/13/348760.html   回复  引用  查看    

#6楼  2007-11-02 11:54 Anytao      

BTemp.printA();的输出是可访问级别影响产生的结果;
ATemp.printA();则是因为new关键字的阻隔作用产生的结果。
不过这个例子很不错,有点儿意思:-)   回复  引用  查看    

#7楼  2007-11-02 12:01 A.Z* [未注册用户]

private无法呈现多态,public可以,和new无关。   回复  引用  查看    

#8楼  2007-11-02 12:12 Silent Void      

在Visual Studio中启用非托管代码调试来进行调试,参考我自己的blog上的文章:深入理解virtual/new/override 这些关键字的意义
http://www.cnblogs.com/happyhippy/archive/2007/07/22/827583.html
  回复  引用  查看    

#9楼  2007-11-02 12:27 Red壁虎 [未注册用户]

--引用--------------------------------------------------
A.Z*: private无法呈现多态,public可以,和new无关。
--------------------------------------------------------

同意。

  回复  引用  查看    

#10楼  2007-11-02 14:15 maomaocatself [未注册用户]

public,private 原因   回复  引用  查看    

#11楼  2007-11-02 14:50 路西菲尔 [未注册用户]

A的作用跟命名空间差不多只不过在使用的范型的时候能把类型参产传给B罢了.   回复  引用  查看    

#12楼  2007-11-02 17:26 MS的明天      

有点意思,学习了   回复  引用  查看    

#13楼  2007-11-02 17:56 chengmeng [未注册用户]

说一个无关的,《深度探索C++对象模型》好象是Stan Lippman的书吧?侯捷应该只是翻译而已   回复  引用  查看    

#14楼  2007-11-02 19:39 徐少侠      

原始程序输出两个A
BTemp.printA();
ATemp.printA();
类型为类B的变量BTemp,引用方法printA
查看类B定义,存在一个匹配的无参方法printA和一个从A类继承来的printA,同样无参
但是由于在B类内定义无参方法printA时没有访问修饰符,因此默认是私有的。
因此在Main方法里,其实就是在类A的上下文里是不能访问的,而基类的相同签名的方法虽然也是没有访问修饰符,也是私有的,但是在类A的上下文范围内,因此是可以访问的。
所以使用类A的printA方法,输出A

类型为A的变量ATemp,引用方法printA
查看类A定义,存在一个匹配的无参方法printA,默认访问性是私有,理由同前,因此可以访问。
输出A

将注释部分修改成Public开头
BTemp.printA();
ATemp.printA();
类型为类B的变量BTemp,引用方法printA
查看类B定义,存在一个匹配的无参方法printA和一个从A类继承来的printA,同样无参
但是由于在B类内定义无参方法printA时有访问修饰符,且是Public的,因此可以访问。
同时,而基类的相同签名的方法虽然也是没有访问修饰符,也是私有的,但是在类A的上下文范围内,因此是可以访问的。
最后考虑到类B的这个方法有new关键字,因此语义是隐藏基类的同签名方法。因此最后只能访问类B自身的方法。
所以使用类B的printA方法,输出B

类型为A的变量ATemp,引用方法printA
同上,没有区别,输出A

仔细看整个过程,和new运算符还有一点点关系,不信,去掉new你看看
虽然程序依然运行,结果也不变,但是编译器会有所警告
警告 1 “ConsoleApplication1.A.B.printA()”隐藏了继承的成员“ConsoleApplication1.A.printA()”。如果是有意隐藏,请使用关键字 new。

问题的主要部分还是在于默认访问修饰符是private以及private的访问范围上。   回复  引用  查看    

#15楼  2007-11-03 00:10 lin203 [未注册用户]

真有意思!!   回复  引用  查看    

#16楼 [楼主] 2007-11-05 13:49 暗香浮动      

近两天出差了。
刚回来,看到大家的回复,我再仔细分析一下。

感谢上面所有的人的回复。严重感谢大家的关注及分析。   回复  引用  查看    

#17楼  2007-11-05 16:20 zhao_1401 [未注册用户]

c# primer 第三章有详细的说明。   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-11-02 10:31 编辑过
 
另存  打印
最新IT新闻:
· 深藏33年Unix操作系统bug被消灭
· Expression Studio 2.0 中文版发布了
· 雅虎首页大变脸 阿里风格上身
· 万名Linux使用者向暴雪请愿Linux版《Diablo III》
· 56.com我乐网将全面转行 退出视频行业
 


导航

公告

diablo3 haha 6-30 17:21
<2007年11月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

统计

与我联系

常用链接

留言簿(2)

我管理的小组

我参与的团队

我的标签

随笔分类

随笔档案

文章分类

舎友

搜索

最新评论

阅读排行榜

评论排行榜