CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

C#、C++和Java中重载和覆盖的一点问题

楼主dx20()2006-03-12 14:45:54 在 C/C++ / C++ 语言 提问

废话少说,先看一个简单的C++程序:  
  #include   <iostream>  
  using   namespace   std;  
   
  class   myFirst  
  {  
          public:  
                  void   funcA()  
                  {  
                          cout<<"这是myFirst类的非虚拟函数\n";  
                  }          
                  virtual   void   funcB()  
                  {  
                          cout<<"这是myFirst类的虚拟函数\n";  
                  }  
  };        
  class   mySecond   :   public   myFirst  
  {  
          public:  
                  void   funcA()  
                  {  
                          cout<<"这是mySecond类的非虚拟函数\n";  
                  }          
                  virtual   void   funcB()  
                  {  
                          cout<<"这是mySecond类的虚拟函数\n";  
                  }  
  };            
   
  int   main()  
  {  
          mySecond   bb;  
          ①     bb.funcA();  
          ②     bb.funcB();  
          ③     ((myFirst*)(&bb))->funcA();  
          ④     ((myFirst*)(&bb))->funcB();  
          ⑤     ((myFirst)(bb)).funcA();  
          ⑥     ((myFirst)(bb)).funcB();  
          return   0;    
  }  
  1和2的输出就不说了,很明确;5和6是向上强制转型(upcasting),将会造成对象的内容被切割;小弟不明白3和4的输出,主要就是(myFirst*)(&bb)这个表达式(我理解是把bb的地址形式转换为myFirst的地址形式),这个表达式对bb的内容有什么样的影响,对于输出的原因不太清楚,烦请各位高手解答一下,最好能从本质上解释。整个程序的输出结果如下所示:  
   
  这是mySecond类的非虚拟函数  
  这是mySecond类的虚拟函数  
  这是myFirst类的非虚拟函数  
  这是mySecond类的虚拟函数  
  这是myFirst类的非虚拟函数  
  这是myFirst类的虚拟函数  
  ******************************************    
   
  下面是同样内容的C#程序:  
  using   System;  
  using   System.Collections.Generic;  
  using   System.Text;  
   
  namespace   虚函数测试Cs  
  {  
        public   class   myFirst  
        {  
              public   void   funcA()  
                  {  
                          Console.WriteLine("这是myFirst类的非虚拟函数");  
                  }          
              public   virtual   void   funcB()  
                  {  
                          Console.WriteLine("这是myFirst类的虚拟函数");  
                  }  
        };        
      public   class   mySecond   :   myFirst  
      {  
              new   public   void   funcA()  
                  {  
                          Console.WriteLine("这是mySecond类的非虚拟函数");  
                  }          
              public   override   void   funcB()  
                  {  
                          Console.WriteLine("这是mySecond类的虚拟函数");  
                  }  
      };  
  class   Program  
          {  
                  static   void   Main(string[]   args)  
                  {  
                          mySecond   bb   =   new   mySecond();  
                          ①   bb.funcA();  
                          ②   bb.funcB();  
                          ③   ((myFirst)(bb)).funcA();  
                          ④   ((myFirst)(bb)).funcB();  
                    }  
          }  
  }  
  1和2的输出很明确,不说了。  
  C#   和C++在类对象赋值运算符(=)这个地方不一样,C++是对象的复制,而在C#中,”=”复制它的引用,即地址,而不是复制对象。例如有一个类A   ,在C++中,   代码A   a;A   b=a;是生成了两个类对象a和b,且这两个对象里面的数据成员的值应该是一样的,而在C#中,代码   A   a   =   new   A();A   b=a;运行之后,b和a其实指向的地址是同样的,b只是a的一个引用。所以从这个角度来讲,我觉得在C#中,(myFirst)(bb)应该和C++中的(myFirst*)(&bb)在本质上是一样的,经验证,本程序中的3和4与C++程序中的3和4的输出结果是统一的。  
  本程序输出如下:  
  这是mySecond类的非虚拟函数  
  这是mySecond类的虚拟函数  
  这是myFirst类的非虚拟函数  
  这是mySecond类的虚拟函数  
  **********************************************  
     
  下面是同样内容的Java程序:  
  class   myFirst  
  {  
          public   void   funcA()  
                  {  
                          System.out.println("这是myFirst类的非虚拟函数");  
                  }          
  }      
  class   mySecond   extends   myFirst  
  {  
          public   void   funcA()  
                  {  
                  System.out.println("这是mySecond类的非虚拟函数");      
          }          
  }  
   
  public   class   test   {  
  public   static   void   main(String[]   args)   {  
  mySecond   bb=new   mySecond();  
  ①   bb.funcA();  
  ②   ((myFirst)bb).funcA();  
  }  
  }  
  由于Java中没有虚拟函数,所以只能测试一下函数覆盖的情况。Java和C#类似,”=”复制类对象之间的地址,我原本以为1和2的输出应该和C#程序中的3和4的输出统一,不过结果却出乎我的意料,程序的输出如下:  
  这是myFirst类的非虚拟函数  
  这是myFirst类的非虚拟函数  
     
  所以小弟的第二个问题是这个Java程序这样输出的原因。另外,我刚刚学Java,看代码看的不是很多,但似乎没有见到Java中有(myFirst)bb这样的用法,是不是Java把C++中一切可能导致歧义的用法都抛弃不用了?呵呵,纯属瞎想,还请高手指出真正的原因。  
  问题点数:100、回复次数:3Top

1 楼guoxiaoli(半导体)回复于 2006-03-12 15:16:42 得分 50

针对C++  
   
   
  由于funcA是非虚函数,所以    
  ((myFirst*)(&bb))->funcA();//这种对bb的强制类型转换可以按常规思维去考虑  
   
   
  一旦套上了虚函数的概念  
  ((myFirst*)(&bb))->funcB();//就要按照虚函数的概念,子类的对象指针在调用虚函数的过程中要采取向下看的规则!  
   
  本质大概就是虚函数内部的机制和指针与引用的内部机制吧!  
   
  有待研究!  
   
  Top

2 楼junguo(junguo)回复于 2006-03-12 15:32:13 得分 50

③     ((myFirst*)(&bb))->funcA();  
          ④     ((myFirst*)(&bb))->funcB();  
   
  其实是编译器在起作用,只有通过指针来调用函数,才会存在多态的情况.你的4中强制转换成了基类的指针,调用虚函数它就会通过虚拟函数表来调用.而虚拟函数表是在对象bb中,他就会调用派生类的对象而不是基类的函数.你可以找c++   对象模型   那本书看看.  
   
  C#中的对象都是引用类型的,基类指向派生类的时候,调用虚函数就通过虚函数表.  
   
  java中应该有自己的虚函数机制,你写的好象不对.不过我也不熟悉java.Top

3 楼dx20()回复于 2006-03-12 22:41:01 得分 0

不好意思     那个Java的程序输出有错误,输出应该都是:这是mySecond类的非虚拟函数  
  请各位高手继续分析Top

相关问题

  • C#、C++和Java中重载和覆盖的一点问题
  • C++重载问题
  • C++的重载问题
  • c++ 输出符的重载??
  • 重载和覆盖的好处
  • 多态 重载 重写 覆盖??
  • 虚函数 重载 覆盖 的问题。
  • 关于C++模板重载问题
  • 在Dev-C++重载运算符问题
  • C++为什么不这样重载>>

关键词

  • c#
  • c++
  • 函数
  • 虚拟
  • java
  • 指针
  • 代码
  • 转换
  • 内容
  • myfirst

得分解答快速导航

  • 帖主:dx20
  • guoxiaoli
  • junguo

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo