不好意思,分散光了,等有分之后立马就给。
废话少说,先看一个简单的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++中一切可能导致歧义的用法都抛弃不用了?呵呵,纯属瞎想,还请高手指出真正的原因。