static_cast与dynamic_cast的比较

static_cast与dynamic_cast的比较

最近一直在琢磨类型转换的问题,索性追究到底了。

仍然是前面提到的继承结构:base1、base2、derived,但是base1和derived有同名的、非虚函数,我的目的是:使用子类的对象,调用基类的同名函数(这么做在技术上是完全可能的,因为子类对象包含基类对象嘛!)。

看下面的代码:
#include <boost/cast.hpp> 
#include <iostream> 
using namespace std;
using namespace boost;
class base1
{
public:
  void same_name_fun()
  {
  cout<<"in base1 same_name_fun"<<endl;
  }
  virtual ~base1(){}
};
class base2
{
public:
  void ba2_fun()
  {
  cout<<"base2_fun"<<endl;
  }
};
class derived : public base1,base2
{
public:
  void same_name_fun()
  {
  cout<<"in derived same_name_fun"<<endl;
  }
  void de_fun()
  {
  cout<<"de_fun"<<endl;
  }
};
int main()
{
  derived obj;
  obj.same_name_fun();
  (static_cast<base1>(obj)).same_name_fun();
  return 0;
}

你认为我如果将static_cast换成dynamic_cast,会有什么样的结果?经过实验,结果是:编译无法通过!提示:

'class base1' : invalid target type for dynamic_cast

也就是说,使用dynamic_cast不能转换成base1。这就引出一个问题:static_cast和dynamic_cast的区别是什么?

说得理论点,是动态和静态、编译期间决定和运行期间决定转换正确与否的区别;说得具体点,还是看代码吧:

代码1:

 
int main()
{
  int i = 100;
  void * p =(void *)&i;
// static_cast<int>(p); 
  int j = (int)(p);
  return 0;
}

在代码1中,妄图将void*转换成int型,static_cast是不干的,dynamic_cast就更别提了;要做这种无法无天的事情,你只能使用C的强制转换;看来,并不能完全说static_cast是强制转换的替代品......

 

代码2:

 
class Base  
{
public:
  virtual ~Base(){} //donnt forget : at least one virtual function..... 
};  
class A : public Base {};  
class B : public Base {};  
class AB : public A, public B {};  
int main()  
{  
  AB ab;  
  B *b = &ab;  
// A *a = static_cast<A *>(b);  
  A * a = dynamic_cast<A*>(b);
  return 0;  
}  

在代码2中,dynamic_cast的转换可以看做2步并作一步:将b 转换为AB*类型,然后再转换为A*类型,毕竟这个指针指向的是AB类型的对象;static_cast就没这个本事了。

在网上搜索一些答案,大部分不详细,有的还不准确,具体应用的例子很少(非static_cast不可,或者非dynamic_cast不可的这种例子),参考意见:

static_cast: 静态强制;不能在无关的指针之间进行static类型强制

dynamic_cast的主要目的是:  
  1)它返回派生类对象的地址;  
  2)它测试基类指针是否指向下一尖括号<>中所指定类型的对象 

我想:static_cast不需要RTTI,在使用的时候不需要基类声明虚函数,这就是一个很明显的区别了!至于说使用的详细用法,参考以上的代码,以及cast操作的“主要目的”,才是正确的理解方式;没必要钻牛角尖了——毕竟,实现某种功能,我们的方法也不止一种,有时候,丑陋点就丑陋点吧!自己明白、看得懂、不出错就行了!

 

另外,如果想调用子类对象的基类函数,除了static_cast以外,也可以使用暴力转换:
((base1)obj).same_name_fun();

这种方法实在是相当的丑陋(括号太多),而且,你需要明确base1和derived的关系,才能写出这样的代码呢。

如果在类当中实现同名函数,方便多了:
#include <iostream> 
using namespace std;
class Base
{
public:
  void fun(){}
};
class derived :public Base
{
public:
  void fun()
  {
  Base::fun();//就这么可以引用到基类的函数
  cout<<"derived"<<endl;
  }
};
void main()
{
  derived obj;
  obj.fun();
}

呼呼......学会使用dynamic_cast,方便一点吧!一句话就完成转换了,方便。

下面也是一个 可以使用static_cast而不能使用dynamic_cast的情况,似乎dynamic_cast适合指针,不适合具体类型(也就是<>里面只能包含指针类型或者引用类型)?
#include <iostream> 
using namespace std;
class Base
{
public:
  virtual ~Base(){}
  void fun(){}
};
class derived :public Base
{
public:
  void fun()
  {
  Base::fun();
  cout<<"derived"<<endl;
  }
};
void main()
{
  derived obj;
  (static_cast<Base>(obj)).fun();
// (dynamic_cast<Base>(obj)).fun(); 
}
是不是很有意思?哈哈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值