精华内容
下载资源
问答
  • 向下转型 不能在对象之间转换。只能在指针指针之间、基类左值派生类引用之间转换。 危险是什么意思?应该是指把基类对象的地址给了派生类对象(向下转换)。派生类对象如果拥有自己独有,而基类没有的成员变量,...

    向上转型

    派生类对象转型为基类对象(包括指针和对象),直接转化由编译器自动完成,不用cast,并且是绝对安全的。
    内存里面:基类对象相当于只是换了个地址。换成了派生类对象中存储基类成员的内存地址。但是派生类对象中有的,基类没有的那些变量仍然留在了内存中。(保留了再次从基类转换成派生类的可能性)

    向下转型

    不能在对象之间转换。只能在指针和指针之间、基类左值和派生类引用之间转换。
    危险是什么意思?应该是指把基类对象的地址给了派生类对象(向下转换)。派生类对象如果拥有自己独有,而基类没有的成员变量,就是危险的。因为当派生类对象试图是访问这些独有的成员的时候,访问的其实是未知的内存空间。但是如果基类对象原本指向的就是派生类的空间,这个转换就是安全的。
    内存里面:相当于把基类起始地址赋值给派生类对象,因为基类有的成员,派生类中也一定有。

    使用场景

    1、向上转型:可以实现动态多态,即基类对象执行的方法实际上是运行过程中他的实际类型的方法。这时候调用的基类方法,实际上是派生类的方法。
    2、向下转型:向下转型是在向上转型的前提上完成的,如果没有向上转型(从派生类变成基类),向下转型是危险的。那么为什么要向下转型呢?因为向上转型之后的对象变成了基类对象,只能执行基类的方法,而有些方法是派生类独有的,为了执行这些方法,就需要向下转型回来。

    (个人理解,有错请指出)

    展开全文
  • class parent { }; class son:public parent { };
  • 父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。 动态转换静态转换,dynamic_cast<type_id>...

    子类转换为父类:向上转型,使用dynamic_cast<type_id>(expression),这种转换相对来说比较安全不会有数据的丢失;

    父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。

    动态转换和静态转换,dynamic_cast<type_id>(expression),static_cast<type_id>(expression),表示的是将expression转换为type_id类型数据,动态转换一般是子类的指针或者引用转换为父类的指针或者引用,静态转换常用用于数值数据类型的转换。

    https://www.jb51.net/article/78145.htm

    dynamic_cast 运算符
    将操作数 expression 转换成类型为type-id 的对象。
    语法

    1

    dynamic_cast < type-id > ( expression )

    备注
    type-id 必须是一个指针或引用到以前已定义的类类型的引用或“指向 void 的指针”。如果 type-id 是指针,则expression 的类型必须是指针,如果 type-id 是引用,则为左值。
    有关静态和动态强制转换之间区别的描述,以及各在什么情况下适合使用,请参见 static_cast。
    在托管代码中的 dynamic_cast的行为中有两个重大更改。
    为指针的dynamic_cast 对指向装箱的枚举的基础类型的指针将在运行时失败,则返回 0 而不是已转换的指针。
    dynamic_cast 将不再引发一个异常,当 type-id 是指向值类型的内部指针,则转换在运行时失败。该转换将返回 0 指示运行值而不是引发。
    如果 type-id 是指向 expression的明确的可访问的直接或间接基类的指针,则结果是指向 type-id 类型的唯一子对象的指针。例如:

    // dynamic_cast_1.cpp
    // compile with: /c
    class B { };
    class C : public B { };
    class D : public C { };

    void f(D* pd) {
    C* pc = dynamic_cast<C*>(pd); // ok: C is a direct base class
    // pc points to C subobject of pd
    B* pb = dynamic_cast<B*>(pd); // ok: B is an indirect base class
    // pb points to B subobject of pd
    }

    此转换类型称为“向上转换”,因为它将在类层次结构上的指针,从派生的类移到该类派生的类。向上转换是一种隐式转换。
    如果 type-id 为 void*,则做运行时进行检查确定 expression的实际类型。结果是指向 by expression 的完整的对象的指针。例如:

    // dynamic_cast_2.cpp
    // compile with: /c /GR
    class A {virtual void f();};
    class B {virtual void f();};

    void f() {
    A* pa = new A;
    B* pb = new B;
    void* pv = dynamic_cast<void*>(pa);
    // pv now points to an object of type A

    pv = dynamic_cast<void*>(pb);
    // pv now points to an object of type B
    }

    如果 type-id 不是 void*,则做运行时进行检查以确定是否由 expression 指向的对象可以转换为由 type-id指向的类型。
    如果 expression 类型是 type-id类型的基类,则做运行时检查来看是否 expression 确实指向 type-id类型的完整对象。如果为 true,则结果是指向 type-id类型的完整对象的指针。例如:

    // dynamic_cast_3.cpp
    // compile with: /c /GR
    class B {virtual void f();};
    class D : public B {virtual void f();};

    void f() {
    B* pb = new D; // unclear but ok
    B* pb2 = new B;

    D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D
    D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D
    }

    此转换类型称为“向下转换”,因为它将在类层次结构下的指针,从给定的类移到该类派生的类。
    对于多重继承,引入多义性的可能性。考虑下图中显示的类层次结构。
    对于 CLR 类型,如果转换可以隐式执行,则 dynamic_cast 结果为 no-op,如果转换失败,则 MSIL isinst 指令将执行动态检查并返回 nullptr。
    以下示例使用 dynamic_cast 以确定一个类是否为特殊类型的实例:

    // dynamic_cast_clr.cpp
    // compile with: /clr
    using namespace System;

    void PrintObjectType( Object^o ) {
    if( dynamic_cast<String^>(o) )
    Console::WriteLine(“Object is a String”);
    else if( dynamic_cast<int^>(o) )
    Console::WriteLine(“Object is an int”);
    }

    int main() {
    Object^o1 = “hello”;
    Object^o2 = 10;

    PrintObjectType(o1);
    PrintObjectType(o2);
    }

    显示多重继承的类层次结构
    显示多继承的类层次结构
    指向类型 D 对象的指针可以安全地强制转换为 B 或 C。但是,如果 D 强制转换为指向 A 对象的指针,会导致 A 的哪个实例?这将导致不明确的强制转换错误。若要避免此问题,可以执行两个明确的转换。例如:

    // dynamic_cast_4.cpp
    // compile with: /c /GR
    class A {virtual void f();};
    class B {virtual void f();};
    class D : public B {virtual void f();};

    void f() {
    D* pd = new D;
    B* pb = dynamic_cast<B*>(pd); // first cast to B
    A* pa2 = dynamic_cast<A*>(pb); // ok: unambiguous
    }

    当使用虚拟基类时,其他多义性问题会被引入。考虑下图中显示的类层次结构。

    2016115151645156.jpeg (221×54)

    显示虚拟基类的类层次结构
    在此层次结构中,A 是虚拟基类。对于虚拟基类的定义。给定一个 E 类实例和一个指向 A 子对象的指针,指向 B 指针的 dynamic_cast 将失败于多义性。必须先将强制转换回完整 E 对象,然后以明确的方式反向沿层次结构,到达正确的 B 对象。
    考虑下图中显示的类层次结构。

    2016115151749363.jpeg (339×60)

    给定一个 E 类型的对象和一个指向 D 子对象的指针,从 D 子对象定位到最左侧的 A 子对象,可进行三个转换。可以从 D 指针到 E 指针执行 dynamic_cast 转换,然后从 E 到 B 执行转换(dynamic_cast 或隐式转换),最后从 B 到 A 执行隐式转换。例如:

    // dynamic_cast_5.cpp
    // compile with: /c /GR
    class A {virtual void f();};
    class B : public A {virtual void f();};
    class C : public A { };
    class D {virtual void f();};
    class E : public B, public C, public D {virtual void f();};

    void f(D* pd) {
    E* pe = dynamic_cast<E*>(pd);
    B* pb = pe; // upcast, implicit conversion
    A* pa = pb; // upcast, implicit conversion
    }

    dynamic_cast 运算符还可以使用执行 “相互转换”。使用同一个类层次结构可能进行指针转换,例如: 从B 子对象转换到D子对象(只要整个对象是类转换型E。
    考虑相互转换,实际上从指针转换到 D 到指针到最左侧的 A 子对象只要两个步骤。可以从 D 到 B 执行相互转换,然后从 B 到 A 执行隐式转换。例如:

    // dynamic_cast_6.cpp
    // compile with: /c /GR
    class A {virtual void f();};
    class B : public A {virtual void f();};
    class C : public A { };
    class D {virtual void f();};
    class E : public B, public C, public D {virtual void f();};

    void f(D* pd) {
    B* pb = dynamic_cast<B*>(pd); // cross cast
    A* pa = pb; // upcast, implicit conversion
    }

    通过 dynamic_cast 将 null 指针值转换到目标类型的 null 指针值。
    当您使用 dynamic_cast < type-id > ( expression )时,如果expression无法安全地转换成类型 type-id,则运行时检查会引起变换失败。例如:

    // dynamic_cast_7.cpp
    // compile with: /c /GR
    class A {virtual void f();};
    class B {virtual void f();};

    void f() {
    A* pa = new A;
    B* pb = dynamic_cast<B*>(pa); // fails at runtime, not safe;
    // B not derived from A
    }

    指针类型的非限定转换的值是 null 指针。引用类型的非限定转换会引发 bad_cast 异常。 如果 expression 不指向也不引用有效的对象,则__non_rtti_object 异常引发。
    有关异常 __non_rtti_object 的解释,请参见 typeid。
    以下示例创建基类(结构 A)指针,为一个对象(结构 C)。这以及在该情况是虚函数,启用运行时多态性。
    该示例也在层次结构中调用非虚函数。

    // dynamic_cast_8.cpp
    // compile with: /GR /EHsc
    #include <stdio.h>
    #include

    struct A {
    virtual void test() {
    printf_s(“in A\n”);
    }
    };

    struct B : A {
    virtual void test() {
    printf_s(“in B\n”);
    }

    void test2() {
    printf_s(“test2 in B\n”);
    }
    };

    struct C : B {
    virtual void test() {
    printf_s(“in C\n”);
    }

    void test2() {
    printf_s(“test2 in C\n”);
    }
    };

    void Globaltest(A& a) {
    try {
    C &c = dynamic_cast<C&>(a);
    printf_s(“in GlobalTest\n”);
    }
    catch(std::bad_cast) {
    printf_s(“Can’t cast to C\n”);
    }
    }

    int main() {
    A *pa = new C;
    A *pa2 = new B;

    pa->test();

    B * pb = dynamic_cast<B *>(pa);
    if (pb)
    pb->test2();

    C * pc = dynamic_cast<C *>(pa2);
    if (pc)
    pc->test2();

    C ConStack;
    Globaltest(ConStack);

    // will fail because B knows nothing about C
    B BonStack;
    Globaltest(BonStack);
    }

    输出:

    in C
    test2 in B
    in GlobalTest

    static_cast 运算符
    仅根据表达式中存在的类型,将 expression 转换为 type-id, 类型。
    语法
    1

    static_cast ( expression )

    备注
    在标准 C++ 中,不进行运行时类型检查来帮助确保转换的安全。在 C++/CX 中,将执行编译时和运行时检查。
    static_cast 运算符可用于将指向基类的指针转换为指向派生类的指针等操作。此类转换并非始终安全。
    通常使用 static_cast 转换数值数据类型,例如将枚举型转换为整型或将整型转换为浮点型,而且你能确定参与转换的数据类型。 static_cast 转换安全性不如 dynamic_cast 转换,因为 static_cast 不执行运行时类型检查,而 dynamic_cast 执行该检查。对不明确的指针的 dynamic_cast 将失败,而 static_cast 的返回结果看似没有问题,这是危险的。尽管 dynamic_cast 转换更加安全,但是 dynamic_cast 只适用于指针或引用,而且运行时类型检查也是一项开销。
    在下面的示例中,因为 D 可能有不在 B 内的字段和方法,所以行 D* pd2 = static_cast<D*>(pb); 不安全。但是,因为 D 始终包含所有 B,所以行 B* pb2 = static_cast<B*>(pd); 是安全的转换。

    // static_cast_Operator.cpp
    // compile with: /LD
    class B {};

    class D : public B {};

    void f(B* pb, D* pd) {
    D* pd2 = static_cast<D*>(pb); // Not safe, D can have fields
    // and methods that are not in B.

    B* pb2 = static_cast<B*>(pd); // Safe conversion, D always
    // contains all of B.
    }

    与 dynamic_cast 不同,pb 的 static_cast 转换不执行运行时检查。由 pb 指向的对象可能不是 D 类型的对象,在这种情况下使用 *pd2 会是灾难性的。例如,调用 D 类(而非 B 类)的成员函数可能会导致访问冲突。
    dynamic_cast 和 static_cast 运算符可以在整个类层次结构中移动指针。然而,static_cast 完全依赖于转换语句提供的信息,因此可能不安全。例如:

    // static_cast_Operator_2.cpp
    // compile with: /LD /GR
    class B {
    public:
    virtual void Test(){}
    };
    class D : public B {};

    void f(B* pb) {
    D* pd1 = dynamic_cast<D*>(pb);
    D* pd2 = static_cast<D*>(pb);
    }

    如果 pb 确实指向 D 类型的对象,则 pd1 和 pd2 将获取相同的值。如果 pb == 0,它们也将获取相同的值。
    如果 pb 指向 B 类型的对象,而非指向完整的 D 类,则 dynamic_cast 足以判断返回零。但是,static_cast 依赖于程序员的断言,即 pb 指向 D 类型的对象,因而只是返回指向那个假定的 D 对象的指针。
    因此,static_cast 可以反向执行隐式转换,而在这种情况下结果是不确定的。这需要程序员来验证 static_cast 转换的结果是否安全。
    该行为也适用于类以外的类型。例如,static_cast 可用于将 int 转换为 char。但是,得到的 char 可能没有足够的位来保存整个 int 值。同样,这需要程序员来验证 static_cast 转换的结果是否安全。
    static_cast 运算符还可用于执行任何隐式转换,包括标准转换和用户定义的转换。例如:

    // static_cast_Operator_3.cpp
    // compile with: /LD /GR
    typedef unsigned char BYTE;

    void f() {
    char ch;
    int i = 65;
    float f = 2.5;
    double dbl;

    ch = static_cast(i); // int to char
    dbl = static_cast(f); // float to double
    i = static_cast(ch);
    }

    // static_cast_Operator_3.cpp
    // compile with: /LD /GR
    typedef unsigned char BYTE;

    void f() {
    char ch;
    int i = 65;
    float f = 2.5;
    double dbl;

    ch = static_cast(i); // int to char
    dbl = static_cast(f); // float to double
    i = static_cast(ch);
    }

    static_cast 运算符可以将整数值显式转换为枚举类型。如果整型值不在枚举值的范围内,生成的枚举值是不确定的。
    static_cast 运算符将 null 指针值转换为目标类型的 null 指针值。
    任何表达式都可以通过 static_cast 运算符显式转换为 void 类型。目标 void 类型可以选择性地包含 const、volatile 或 __unaligned 特性。
    static_cast 运算符无法转换掉 const、volatile 或 __unaligned 特性。

    展开全文
  • 父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。 动态转换静态转换,dynamic_cast(expression),static_cast...

    子类转换为父类:向上转型,使用dynamic_cast<type_id>(expression),这种转换相对来说比较安全不会有数据的丢失;

    父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。

    动态转换和静态转换,dynamic_cast<type_id>(expression),static_cast<type_id>(expression),表示的是将expression转换为type_id类型数据,动态转换一般是子类的指针或者引用转换为父类的指针或者引用,静态转换常用用于数值数据类型的转换。

    参考一下连接:http://www.jb51.net/article/78145.htm

    展开全文
  • Java中的向上转型和向下转型

    千次阅读 2015-11-06 17:41:38
    转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父类的功能,如果父类不...向下转型:父类引用的对象转换为子类类型称为向下转型向上转型向上转型问题的由来:

    转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。

    向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口

    向下转型:父类引用的对象转换为子类类型称为向下转型。


    向上转型:

    向上转型问题的由来:

    首先是方法的参数是父类对象,传入子类对象是否可行
    然后引出Parent p = new Children();
    这句代码不是很理解,google的过程中引出向上转型
    要理解向上转型又引出了动态绑定

    从动态绑定又引出了静态绑定

    前者是一个向上转型,Animal dog 引用指向new Dog();子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。


    程序绑定的概念:
    绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定动态绑定;或者叫做前期绑定后期绑定

     

    静态绑定
    前期绑定:在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。
    针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定

     

    动态绑定
    后期绑定:在运行时根据具体对象的类型进行绑定。
    若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。


    动态绑定的过程

    • 虚拟机提取对象的实际类型的方法表;
    • 虚拟机搜索方法签名;
    • 调用方法。

     

    关于绑定相关的总结:
    在了解了三者的概念之后,很明显我们发现java属于后期绑定。在java中,几乎所有的方法都是后期绑定的,在运行时动态绑定方法属于子类还是基类。但是也有特殊,针对static方法和final方法由于不能被继承,因此在编译时就可以确定他们的值,他们是属于前期绑定的。


    特别说明的一点是,private声明的方法和成员变量不能被子类继承,所有的private方法都被隐式的指定为final的(由此我们也可以知道:将方法声明为final类型的一是为了防止方法被覆盖,二是为了有效的关闭java中的动态绑定)。java中的后期绑定是有JVM来实现的,我们不用去显式的声明它,而C++则不同,必须明确的声明某个方法具备后期绑定。

     

    java当中的向上转型或者说多态是借助于动态绑定实现的,所以理解了动态绑定,也就搞定了向上转型和多态
    前面已经说了对于java当中的方法而言,除了final,static,private和构造方法是前期绑定外,其他的方法全部为动态绑定。而动态绑定的典型发生在父类和子类的转换声明之下:
    比如:Parent p = new Children();


    其具体过程细节如下:
    1:编译器检查对象的声明类型和方法名。假设我们调用x.f(args)方法,并且x已经被声明为C类的对象,那么编译器会列举出C类中所有的名称为f的方法和从C类的超类继承过来的f方法


    2:接下来编译器检查方法调用中提供的参数类型。如果在所有名称为f 的方法中有一个参数类型和调用提供的参数类型最为匹配,那么就调用这个方法,这个过程叫做“重载解析” 

     
    3:当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。假设实际类型为D(C的子类),如果D类定义了f(String)那么该方法被调用,否则就在D的超类中搜寻方法f(String),依次类推

     

    上面是理论,下面看几个示例(示例来自网络):

    public class Father {  
      public void method() {  
        System.out.println("父类方法,对象类型:" + this.getClass());  
      }  
    }  
        
    public class Son extends Father {  
      public static void main(String[] args) {  
        Father sample = new Son();//向上转型  
        sample.method();  
      }  
    }  

    声明的是父类的引用,但是执行的过程中调用的是子类的对象,程序首先寻找子类对象的method方法,但是没有找到,于是向上转型去父类寻找

    public class Son extends Father {  
      public void method() {  
        System.out.println("子类方法,对象类型:" + this.getClass());  
      }  
        
      public static void main(String[] args) {  
        Father sample = new Son();//向上转型  
        sample.method();  
      }  
    }  

    由于子类重写了父类的method方法,根据上面的理论知道会去调用子类的method方法去执行,因为子类对象有method方法而没有向上转型去寻找

     

    前面的理论当中已经提到了java的绑定规则,由此可知,在处理java类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以找到子类,而对象的属性还是父类的属性。

    代码如下:

    public class Father {  
      
      protected String name="父亲属性";  
        
      public void method() {  
        System.out.println("父类方法,对象类型:" + this.getClass());  
      }  
    }  
        
    public class Son extends Father {  
      protected String name="儿子属性";  
        
      public void method() {  
        System.out.println("子类方法,对象类型:" + this.getClass());  
      }  
        
      public static void main(String[] args) {  
        Father sample = new Son();//向上转型  
        System.out.println("调用的成员:"+sample.name);  
      }  
    }  

     结论,调用的成员为父亲的属性。

    这个结果表明,子类的对象(由父类的引用handle)调用到的是父类的成员变量。所以必须明确,运行时(动态)绑定针对的范畴只是对象的方法。如果想调用子类的成员变量,必须将成员变量封装成getValName()形式。

    现在试图调用子类的成员变量name,该怎么做?最简单的办法是将该成员变量封装成方法getter形式。

    代码如下:

    public class Father {  
      protected String name = "父亲属性";  
      public String getName() {  
        return name;  
      }  
      public void method() {  
        System.out.println("父类方法,对象类型:" + this.getClass());  
      }  
    }  
        
    public class Son extends Father {  
      protected String name="儿子属性";  
        
      public String getName() {  
        return name;  
      }  
        
      public void method() {  
        System.out.println("子类方法,对象类型:" + this.getClass());  
      }  
        
      public static void main(String[] args) {  
        Father sample = new Son();//向上转型  
        System.out.println("调用的成员:"+sample.getName());  
      }  
    }  

    结果:调用的是儿子的属性

    向下转型:

    在向下转型过程中,分为两种情况:

    情况一:如果父类引用的对象是指向子类的对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。

    情况二:如果父类引用的对象是父类本身对象,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。解决方案:可以使用instanceof来避免出错此类错误。实例如下:

    public class Girl {
    
             public void smile(){
    
                  System.out.println("girl smile()...");
    
             }
    
    }
    
    class MMGirl extends Girl{
    
                       @Override
    
             public void smile() {
    
                  System.out.println("MMirl smile sounds sweet...");
    
             }
    
             public void c(){
    
                  System.out.println("MMirl c()...");
    
             }
    
    }
    
    class main{
    
        public static void main(String[] args) {
    
              Girl g1=new MMGirl(); //向上转型
    
              g1.smile();
    
              MMGirl mmg=(MMGirl)g1;    //向下转型,编译和运行皆不会出错
    
              mmg.smile();
    
              mmg.c();
    
              Girl g2=new Girl();
    
               //MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但会运行会出错
    
               //mmg1.smile();
    
               //mmg1.c();
               if(g2 instanceof MMGirl){
                     MMGirl mmg1=(MMGirl)g2;
                     mmg1.smile();
                     mmg1.c();
               }
             }}

    总结:

    1、父类引用可以指向子类对象,子类引用不能指向父类对象。

    2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。

       如Father father = new Son();

    3、把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。

       如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;

       其中father前面的(Son)必须添加,进行强制转换。

    4、upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效

    5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。



    展开全文
  • 父子对象之间的转换分为了向上转型和向下转型,它们区别如下: 向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换 向下转型 : 通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换 ...
  • 父子对象之间的转换分为了向上转型和向下转型,它们区别如下: 向上转型 : 子类引用的对象转换为父类类型,这种属于自动转换。 向下转型 : 父类引用的对象转换为子类类型,这需要借助强制转换。 其实我更想说,从子转...
  • C++ 向上转型

    2020-03-14 15:09:47
    C++ 中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值;反过来,float 类型的数据在经过类型转换后也可以赋值给 int 类型的...
  • 征文 | 从高考,到程序员 深度学习与TensorFlow入门...java向上转型向下转型 标签: java 转型 2017-06-18 09:31 5人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: Java学习
  • C++向上转型

    2017-08-09 22:09:40
    在 C/C++ 中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值;反过来,float 类型的数据在经过类型转换后也可以赋值给 int ...
  • 文章目录父子对象之间的转换分为了向上转型和向下转型,它们区别如下:向上转型注意:向上转型时,父类只能调用父类方法或者子类覆写后的方法,而子类中的单独方法则是无法调用的.向下转型instanceof向下转型意义 父子...
  • //基本的向上构造 #include <iostream>...
  • 多态 将一条消息发给对象时,如果并不知道对方的具体类型是什么,但采取的行动同样是正确的,这种情况就叫 作“多形性”(Polymorphism)....向上转型 public class Player { public void play()...
  • 父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。 动态转换静态转换,dynamic_cast(expression),static_cast...
  • 父子对象之间的转换分为了向上转型和向下转型,它们区别如下: 向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换 向下转型 : 通过父类对象(大范围)实例化子类对象(小范围),这种属于强制转换 ...
  • (二) 向下转型 所谓向下,即父类转为子类,将父类对象强转为子类对象。如: = 父类对象a被强转为了子类对象c。 五. 多态的利弊 (一) 多态的优点 多态能够提高程序的扩展性,当我们定义一个方法时,只需要使用父...
  • C++:向上转型

    千次阅读 2017-05-06 22:11:51
    不过这种转换只有在基类派生类之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。...
  • 向上转型和向下转型 父类:A 子类:B 向上转型: 创建格式: A a= new B(); 向上转型会丢失子类的新增方法,同时会保留子类重写的方法。 向下转型: 创建格式: A a= new B(); B c=(B) a; 向下转型可以得到子类的...
  • 正是大四实习期间,看李兴华老师的Java教学视频再打打基础时,就遇见向上转型向下转型的问题,向上转型倒是通过视频看懂了,向下转型那一段看了好多遍都没懂,上网查资料,也大多一语带过,最后看了《Java编程思想...
  • 我们在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型。 5.13.1 向上转型我们在现实中常常这样说:这个人会唱歌。在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们...
  • 在我们工作的时候通常会看到这样的代码:  Map m = new HashMap... l 是 对象吗?不要急于回答问题,请看下面两行代码:  Human human;  human = new Human("亚当");  这两行代码等同于:Human human = n
  • 向上转型:是指定义一个父类的对象引用可以实现子类特有的方法向上转型:father one=new son();这个语句具体是什么意思呢?“=”号左边是新建一个son类的的对象,“=”号右边是定义一个father类的对象引用one,此处...
  • 多态性 封装 继承 多态 多态性有两种实现模式 方法的多态性 方法的重载:同一个方法名称可以根据传入的参数的类型个数的不同实现不同的...对象向下转型 子类 子类实例 = (子类)父类实例 (强制完成转换) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,580
精华内容 1,832
关键字:

c++向上转型和向下转型

c++ 订阅