关于变量类型、对象类型和强制类型转换的对话

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/YidingHe/article/details/5863585

问:在类型转换时,引用对象的类型是它所属的类,还是它所指的类?

 

答:对象的类型只有一个,就是调用它的 getClass() 方法获得的类型。在被引用时,引用它的变量可以是该类型,也可以是该类型的父类。例如一个 Integer 对象,引用它的变量可以是 Integer 类型,也可以是它的父类 Number 类型,甚至就是 Object 也可以。

 

问:在以下代码中:
Class T1 {}
Class T2 extends T1 {}
Class T3 extends T2 {}
Class Test {
    public static void main(String [ ] args) {

        T1 t1=new T3();  
        T2 t2=(T2)t1;  //在类型转换时,是由T1向T2转换,还是由T3向T2转换?
                       //因此,它是不是强制转换呢?
    }
}

 

答:t1 是一个变量,这个变量的类型是 T1;t1 指向一个对象,这个对象的类型是 T3。t2 是一个变量,这个变量的类型是 T2;t2 指向一个对象,这个对象同样是 t1 指向的对象。所以这个类型转换实际上是将 T3 类型的对象引用为 T2 类型。

 

问:因此,它是向上提升了,所以不是强制转换是吗?

 

答:可以这么理解,因为所有的强制类型转换是在继承链中转换。例如:Object<-Comparable<-Date<-Timestamp 这个继承链,对于任何一个 Timestamp 对象,你可以将指向它的变量强制转换为 Object、Comparable 或 Date 类型而不会出错;但如果强制转换为其他类型,如 String,就会出错了。

 

问:不是说向上转换都是自动转换吗?

 

答:是的,向上转换不需要强制。不管向上向下,其实都不过是变量的类型和其指向的对象类型的匹配问题。

 

问:我还是不明白。那么在:
        T1 t1=new T3();  
     T2 t2=(T2)t1;

中,第一句是自动转换我明白,它是由T3到T1;
第二句为什么是强制转换呢?不是从T3到T2吗?应该是自动转换啊?

 

答:变量的类型在它定义的时候就决定了,而与它实际指向的对象的类型无关。因为变量 t1 的类型是 T1,所以在编译时只能判定 t1 指向的是一个 T1 对象。虽然它在运行的某一时刻时指向一个 T3 对象,但不能因此把 t1 变量看成是 T3 类型的。

 

问:噢,我明白了,谢谢!

展开阅读全文

关于强制类型转换

07-04

有这样一段代码!(摘自侯杰《深入浅出MFC第二章 Object slicing与虚拟函数》)rnclass CObjectrnrnpublic:rn virtual void Serialize();rnrnclass CDocument : public CObjectrnrnpublic:rn void func() rn Serialize();rn rn virtual void Serialize() ;rn;rnrnclass CMyDoc : public CDocumentrnrnpublic:rn virtual void Serialize();rn;rn//------------------------------------------------------------------rnvoid main()rnrn CMyDoc mydoc;rn CMyDoc* pmydoc = new CMyDoc;rnrn cout << "#1 testing" << endl;rn mydoc.func();rnrn cout << "#2 testing" << endl;rn ((CDocument*)(&mydoc))->func();rn//added by me rn ((CDocument*)(pmydoc))->func();rnrn cout << "#3 testing" << endl;rn pmydoc->func();rn rn cout << "#4 testing" << endl;rn ((CDocument)mydoc).func();rnrnrnrn对于test1,test3我都理解了。对于test4,书里面有解释说明,对于test2,我有一个疑惑。rn1.rn把CMyDoc类的指针强制转化成CDocument类的指针,那么这个指针所调用的方法,应该是CDocument的方法了,(这里也就是CDocument->func()),func()里面调用了Serialize()虚拟函数,而CDocument类也声明了这个虚拟函数,所以func()里面调用的Serialize函数就应该是CDocument的函数。rn实际的结果的是调用的仍然是CMyDocument类的Serialize函数。rnrn2.它和test4中((CDocument)mydoc).func();这种强制类型转换有什么区别呢?rnrn哪位给解释一下?不胜感激。rn困惑不一的菜鸟rn 论坛

关于两种对象类型使用

09-16

直接描述的我的问题了。rn 我的需求是读取本地或异地的数据,程序中用到ResultSet(本地读取)和DepartResultset(异地读取,自己写的)来获得数据,程序就像这样:rn[code="java"]rn本地:代码一rnconn = DBUtil.getConnection();rn Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,rn ResultSet.CONCUR_UPDATABLE);rn ResultSet rs = null;rn rs = stmt.executeQuery(sql); [/code]rnrn[code="java"]rn异地:代码二rnUnNativeDataSource ds = (UnNativeDataSource) DataSourceFactory.create(DataSourceTypes.UNNATIVETYPE);rn DepartResultset rs = null;rn rn rs = ds.exec(this.postCode,sql);rn rs.first(); [/code]rnrn下面再读取时统一用rs变量来读,如 rn[code="java"]rn代码三:rnif (rs.next()) [/code] rn我想问得是前面怎么设置两个不同类型rs, 怎么判断后给他转换个类型,就像如果true用本地rs,false用异地rs,最主要的是保证代码3不用修改。 n[b]问题补充:[/b]n类被封装了,改不了。rn我最简单的想法就是不用rn[code="java"]if(本地)rn if(rs.next)rn ...rnelse if(异地)rn if(rs.next)rn ...[/code]rnrn省略部分代码量比较大。rn最好就是,[code="java"]Object rs = null;rn if(本地)rn rs = 本地rn elsern rs = 异地rn rn 然后if(rs.next)rn ...[/code]rn有没有这种方式的实现。n[b]问题补充:[/b]n如果本地rnConnection conn = DBUtil.getConnection(); rn Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, rn ResultSet.CONCUR_UPDATABLE); rn ResultSet rs = null; rn rs = stmt.executeQuery(sql); rnrn/*rn如果异地rnUnNativeDataSource ds = (UnNativeDataSource) DataSourceFactory.create(DataSourceTypes.UNNATIVETYPE); rn DepartResultset rs = null; rn rs = ds.exec(this.postCode,sql); rn rs.first(); rn*/rnrnrnif(rs.next())rn ...rnrnrn我要做的是就是把注释的这段也实现出来,这样会不会清楚些。n[b]问题补充:[/b]npublic void test(boolean isNative, Object obj)rnif(flag)rnrs = (ResultSet)Obj;rnelsernrs = (DepartResultset)Obj;rnif(rs.next) ... rnrnrnwangying95599 的做法试过,rs很难定义,定义成Object,它没有.next()方法;定义成ResultSet/DepartResultset,似乎不行。rn最好的做法我想还是异地操作类继承ResultSet类比较好。但是类被封装起来了。想办法沟通去。谢谢大家!n[b]问题补充:[/b]n[quote]使用组合啊,你自定义一个类,做为抽象类,再下面搞两个实现类,一个实现类使用本地的ResultSet做为内在属性,然后覆盖它的某一些方法 rn另一个实现类使用远程的ResultSet做为内在属性,然后覆盖它的某一些方法,不就可以了吗?不需要去改已经封装好的代码,当然,这个方法也只能说是权宜之计,考虑一下,rnwangdgsc (初级程序员) 2009-09-21 [/quote]rnrn这个建议很好啊,虽然没做,但是思路比较清晰了,谢谢wangdgsc!rnAbstractResulsetSet(抽象类)rn|ern|xrn|trn|ern|nrn|d _____NativeResult ResultSet rs; method()return rs;rn|s | rn------|rn |rn _____UnNativeResultrn DepartResultset rs; method()return rs;rn 问答

关于向下强制类型转换!!!多态性!

02-09

// NOTE: You may need to enable RTTI on your compilerrn// before you can execute this application.rn#include rn#include rn#include rn#include rn#include "Employee.h"rn#include "SalariedEmployee.h" rn#include "HourlyEmployee.h"rn#include "CommissionEmployee.h" rn#include "BasePlusCommissionEmployee.h" rnusing namespace std;rnrnint main()rnrn // set floating-point output formattingrn cout << fixed << setprecision( 2 ); rn rn // create vector of four base-class pointersrn vector < Employee * > employees( 4 );rnrn // initialize vector with various kinds of Employeesrn employees[ 0 ] = new SalariedEmployee( rn "John", "Smith", "111-11-1111", 800 );rn employees[ 1 ] = new HourlyEmployee( rn "Karen", "Price", "222-22-2222", 16.75, 40 );rn employees[ 2 ] = new CommissionEmployee( rn "Sue", "Jones", "333-33-3333", 10000, .06 );rn employees[ 3 ] = new BasePlusCommissionEmployee( rn "Bob", "Lewis", "444-44-4444", 5000, .04, 300 );rnrn // polymorphically process each element in vector employeesrn for ( size_t i = 0; i < employees.size(); i++ ) rn rn employees[ i ]->print(); // output employee informationrn cout << endl;rnrn // downcast pointerrn BasePlusCommissionEmployee *derivedPtr =rn dynamic_cast < BasePlusCommissionEmployee * > rn ( employees[ i ] );rnrn // determine whether element points to base-salaried rn // commission employeern if ( derivedPtr != 0 ) // 0 if not a BasePlusCommissionEmployeern rn double oldBaseSalary = derivedPtr->getBaseSalary();rn cout << "old base salary: $" << oldBaseSalary << endl;rn derivedPtr->setBaseSalary( 1.10 * oldBaseSalary );rn cout << "new base salary with 10% increase is: $" rn << derivedPtr->getBaseSalary() << endl;rn // end ifrn rn cout << "earned $" << employees[ i ]->earnings() << "\n\n";rn // end for rn rn // release objects pointed to by vector抯 elementsrn for ( size_t j = 0; j < employees.size(); j++ ) rn rn // output class namern cout << "deleting object of " rn << typeid( *employees[ j ] ).name() << endl;rnrn delete employees[ j ];rn // end forrn // end mainrnrn这一段是要从4种职员里识别出BasePlusCommissionEmployee,并且加薪百分之10,大家看这几句rn BasePlusCommissionEmployee *derivedPtr =rn dynamic_cast < BasePlusCommissionEmployee * > rn ( employees[ i ] );rnrn // determine whether element points to base-salaried rn // commission employeern if ( derivedPtr != 0 ) // 0 if not a BasePlusCommissionEmployeernrn其中用了 dynamic_cast < BasePlusCommissionEmployee * > rn ( employees[ i ] );rn是不是将基类对象转化成了BasePlusCommissionEmployee * ?为什么如果不是BasePlusCommissionEmployee(比如是SalariedEmployee),dynamic_cast <>就会返回值是0呢?rn 求详解 论坛

关于强制类型转换的效率问题

04-08

我有一个基类,然后继承类都会使用到数据库连接rn如果我在基类中声明IDbConnection,那么在继承类中使用时,每次都要强制转换,不知道对效率会有多大影响,这样的好处是代码复用率高rn如果我在基类中不声明IDbConnection,那么我在继承类中将单独的声明各自的connection,这样效率虽高,但代码复用率不高rnrn代码举例如下,请教各位,如果采用IDbConnection的方式,对效率会有多大影响,比之于下面的例子rnrn[code=csharp]rnusing System;rnusing System.Collections.Generic;rnusing System.Linq;rnusing System.Text;rn//rnusing System.Data;rnusing System.Data.SqlClient;rnrnnamespace DBMangerrnrn public class DBManagerBasern rn //在基类中声明一个接口对象rn protected IDbConnection conn; rn rnrn public class DBManagerSqlServer : DBManagerBasern rn public DBManagerSqlServer(string _connStr)rn rn conn = new SqlConnection(_connStr);rn rnrn public void insert(string sqlStr)rn rn //每次使用时转换一次,优点代码少,但是不知道转换的代价是多少rn SqlCommand cmd = new SqlCommand(sqlStr, (SqlConnection)conn);rn rn rnrnrnrnnamespace DBMangerrnrn public class DBManagerBasern rn rnrn public class DBManagerSqlServer : DBManagerBasern rn //在继承类中声明对象rn protected SqlConnection conn;rnrn public DBManagerSqlServer(string _connStr)rn rn conn = new SqlConnection(_connStr);rn rnrn public void insert(string sqlStr)rn rn //不需要转换,效率最高rn SqlCommand cmd = new SqlCommand(sqlStr, conn);rn rn rnrn[/code] 论坛

没有更多推荐了,返回首页