A a=new B();//你这里已经指定了用B去实例化a
B b=(B)a;//所以这里什么都没做,即使不强制转换,a本身就是B的实例化,而不是基类A

解决方案 »

  1.   

    那能解释下
    A a = new A();
                B b = new B();
                b = (B)a;
    为何能编译通过,却运行抛出异常,此时运行时(B)a在做什么?为什么会抛出异常
      

  2.   

    A a=new B();//如果只有这一句代码..虽然a是B类实例.但是假如A类和B类都有hello()方法,那么调用a.hello()执行的是A类的hello()方法,
    B b=(B)a;//这个b才是真正意义上的B类实例...无论用b去调用什么方法.都是用B类的..
      

  3.   

    那能解释下
    A a = new A();
                B b = new B();
                b = (B)a;
    为何能编译通过,却运行抛出异常,此时运行时(B)a在做什么?为什么会抛出异常
    以内存来说,a和b都是指向同一段内存,这是不会报错,所以你a=b在底层的语法中是没有错误的;报错得是编译器对类型的检测即c#语法,A是B的父类,所以可以定义b;
      

  4.   

    那能解释下
    A a = new A();
                B b = new B();
                b = (B)a;
    为何能编译通过,却运行抛出异常,此时运行时(B)a在做什么?为什么会抛出异常
    因为 a是parent class的instance,b和a都属于A的类型,自然可以编译通过,但是一旦运行,
    b = (B)a;违反了 设计模式的里氏替换原则(子可以替换父 , 父不可以替换子)
      

  5.   

    内存地址由16位2进制来表示,分为高8位和低8位当声明一个类时,高8位指向了这个类叫什么,唯一的ID是什么等类本身的信息,这也是我们能通过反射查找到的部分信息而低8位指向的是类内部对外部对象的地址引用,即是说低8位指向了类内部的属性和方法的地址集合而继承,我们可以认为是子类的高8位指向了父类低8位的地址,这样子类就知道了父类所有的属性和方法(这里不讨论private),这些属性和方法的地址也遵循着继承关系,即高8位指向了父类对应属性或方法的地址的低8位类型转换的过程,我们可以认为是一个内存寻址的过程。当A指向B的时候(即A a= new B()),此时查询B的高8位是不是等于A的低8位,等于则此表达式是成立的。当然这是一个链式反应,如果是A:B:C, 如果A a= new C(), 则会根据链式的规则,向上去查找地址,首先找到B,B的低8位是满足C的高8位的,然后通过B的高8位找到了A的低8位,所以此表达式是正确的。而让B b= nwe A()或者C c= new A(),查找A的高8位地址没有找到任何匹配的地址,则此表达式不成立。而B b = (B)a,这种叫显示转换,也叫做强制转换,这是C#这类强类型语言独有的方式,这样做是在编译期在语义上能解释,但并验证这种转换是否正确,实际的转换过程是在runtime,显然A的高8位不符合上述的寻址规则,所以报错当然底层的实现不可能如我所叙述的如此简单,而且语言不同,在寻址方式和地址的使用上也会有区别,但大致就是这么个意思了
      

  6.   

    A a=new B();   // 这里真正制造出来的是B,不是A。假设A=哺乳动物,B = 狗。
    B b=(B)a;
    上帝创建了一个狗,先用哺乳动物表示着,等到有一天,上帝觉得狗这个名称不错,就用狗来表示之前创建的那只A a = new A();//这里真正制造出来的是A,假设A=哺乳动物,B = 狗。
    B b = new B();//这里真正制造出来的是B,假设A=哺乳动物,B = 狗。
    b = (B)a;你觉得哺乳动物可以转换成狗么面向对象是一种用来分析世界的方法~
    你可以多考虑现实中的例子
    如果单单看A转B ,B转A的,很难明白了解面向对象的A a=new B();  
    B b=(B)a;
    这个在内存上是没有变化的~ 只是穿马甲而已~float f = 10;
    int i =(int)f;//虽然i也是10,但内存上已经被去掉了很多个bit了~
    当然这是值类型的,像上面的引用类型的~真真正正的父转子是要报错的,
      

  7.   

    A a=new B();
    这种情况一般普遍的代码中的情况就是:ISomeInterface si = new SomeClass(); // SomeClass 实现了 ISomeInterface
    // 这样,SomeClass 自己定义的很多东西都被过滤了,si 看不到了。si 只看到自己定义的、以及被 SomeClass 重载的那些东西。
      

  8.   

    那能解释下
    A a = new A();
                B b = new B();
                b = (B)a;
    为何能编译通过,却运行抛出异常,此时运行时(B)a在做什么?为什么会抛出异常强制类型转换,这就是告诉编译器你”强制定义类型“了。这实际上就突破了c#的强类型编程的限制。但是.net平台是强类型的系统,它会在给变量赋值时自动去检查一下对象的类型,保证声明兼容性。他不会像javascript那类垃圾动态语言那样,仅仅在你的代码已经走到迷宫里、你按照错误的类型而仿问属性或者函数执行时才崩溃,而是会提前在入口处就给你崩溃。
      

  9.   

    你那种强制类型转换,编译器什么也不做,而且运行时只要.net系统检测到类型兼容,那么直接用变量b引用对象就是了。但是强制类型转换,在c#编译器中还有另外一种用法。我以前举过一个把香蕉强制转换为马的例子,以及把”主语+谓语“转换为句子的例子。http://bbs.csdn.net/topics/360039451