最近一直在琢磨类型转换的问题,索性追究到底了。
仍然是前面提到的继承结构: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();
}
是不是很有意思?哈哈!
static_cast与dynamic_cast的比较
最新推荐文章于 2022-05-15 10:38:31 发布