static_cast与dynamic_cast的比较

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

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

看下面的代码:

  1. #include <boost/cast.hpp>
  2. #include <iostream>
  3. using namespace std;
  4. using namespace boost;
  5. class base1
  6. {
  7. public:
  8.     void same_name_fun()
  9.     {
  10.         cout<<"in base1 same_name_fun"<<endl;
  11.     }
  12.     virtual ~base1(){}
  13. };
  14. class base2
  15. {
  16. public:
  17.     void ba2_fun()
  18.     {
  19.         cout<<"base2_fun"<<endl;
  20.     }
  21. };
  22. class derived : public base1,base2
  23. {
  24. public:
  25.     void same_name_fun()
  26.     {
  27.         cout<<"in derived same_name_fun"<<endl;
  28.     }
  29.     void de_fun()
  30.     {
  31.         cout<<"de_fun"<<endl;
  32.     }
  33. };
  34. int main()
  35. {
  36.     derived obj;
  37.     obj.same_name_fun();
  38.     (static_cast<base1>(obj)).same_name_fun();
  39.     return 0;
  40. }

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

'class base1' : invalid target type for dynamic_cast

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

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

代码1:

 

  1. int main()
  2. {
  3.     int i = 100;
  4.     void * p =(void *)&i;
  5. //  static_cast<int>(p);
  6.     int j = (int)(p);
  7.     return 0;
  8. }

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

 

代码2:

 

  1. class   Base   
  2. {
  3. public:
  4.     virtual ~Base(){} //donnt forget : at least one virtual function.....
  5. };   
  6. class   A   :   public   Base   {};   
  7. class   B   :   public   Base   {};   
  8. class   AB   :   public   A,   public   B   {};   
  9. int     main()   
  10. {   
  11.     AB   ab;   
  12.     B   *b   =   &ab;   
  13. //  A   *a   =   static_cast<A   *>(b);   
  14.     A * a = dynamic_cast<A*>(b);
  15.     return   0;   
  16. }  

在代码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以外,也可以使用暴力转换:

  1. ((base1)obj).same_name_fun();

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

如果在类当中实现同名函数,方便多了:

  1. #include <iostream>
  2. using namespace std;
  3. class Base
  4. {
  5. public:
  6.     void fun(){}
  7. };
  8. class derived :public Base
  9. {
  10. public:
  11.     void fun()
  12.     {
  13.         Base::fun();//就这么可以引用到基类的函数
  14.         cout<<"derived"<<endl;
  15.     }
  16. };
  17. void main()
  18. {
  19.     derived obj;
  20.     obj.fun();
  21. }

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

下面也是一个 可以使用static_cast而不能使用dynamic_cast的情况,似乎dynamic_cast适合指针,不适合具体类型(也就是<>里面只能包含指针类型或者引用类型)?

  1. #include <iostream>
  2. using namespace std;
  3. class Base
  4. {
  5. public:
  6.     virtual ~Base(){}
  7.     void fun(){}
  8. };
  9. class derived :public Base
  10. {
  11. public:
  12.     void fun()
  13.     {
  14.         Base::fun();
  15.         cout<<"derived"<<endl;
  16.     }
  17. };
  18. void main()
  19. {
  20.     derived obj;
  21.     (static_cast<Base>(obj)).fun();
  22.     (dynamic_cast<Base&>(obj)).fun();//引用类型是可以的
  23. //  (dynamic_cast<Base>(obj)).fun();
  24.     
  25. }
是不是很有意思?哈哈!
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值