static_cast可以用来,将指针或者引用转为相关的指针或者引用,譬如派生类转为基类,基类转为派生类,但是安全性必须由程序员自己控制。因为int*和float *是不相关的,所以它们之前的转换不能用static_cast,但可以用传统的强制进行转换,譬如(int *)
要注意的是static_cast只能对有继承关系的类,进行向下转型或者向上转型,如果是两个无关的类,用static_cast转型,编译错误
dynamic_cast在编译期间,只检查被转换类是否有虚表,如果有虚表,则在编译过程中不会出错,这是因为dynamic_cast是在运行期间检查的,如果在运行期间检查两个类之间不能转换,如果是指针则返回NULL,如果是引用则有异常。
class A{ public: virtual void fun() { cout<<"a"<<endl; } }; class B { public: }; int main() { A a; B *b = dynamic_cast<B*>(&a); if(b == NULL) cout<<"NULL"<<endl; }
上述程序如果用static_cast转型,则编译出错
reinterpret_cast,不管两个类之间是否相关,就都可以转型,至于实际运行中是否正确,要看实际的平台。
对于类而言,static_const 只能用于转换指针或者引用的,不用用于转换类
class AA{
};
class BB:public AA{
};
void fun(AA &a){
BB b = static_cast<BB>(a);
}
肯定会编译出错,应该是 BB& b = static_cast<BB &>(a);
还可以用于可以隐式转换的情况的非指针或者引用,譬如:
double d=3.14159265;
int i = static_cast<int>(d);
或者对象之间的转换(不是对象的指针或者引用)
对于代码:
class ad1 { public: ad1() { cerr<<"ad1 construction\n"; } ~ad1() { cerr<<"ad1 deconstruction\n"; } }; class ad2 { public: ad2() { cerr<<"ad2 construction\n"; } ~ad2() { cerr<<"ad2 deconstruction\n"; } }; class test2; class test1 { public: test1(int a):tst_var(a) { cerr<<"test1 construction with para\n"<<tst_var<<endl; } test1() { cerr<<"test1 construction\n"; } test1(test1 &t1) { cerr<<"test1 copy construction ,parameter is test1\n"; } /*test1(test2 &t2) { cerr<<"test1 copy construction ,parameter is test2\n"; }*/ ~test1() { cerr<<"test1 deconstruction\n"<<tst_var<<endl; } void testtry() const; void testtry(); virtual void calc() { cerr<<"int test1\n"<<"sum is "<<Snum<<endl; ++Snum; } void set(int num) { ptd1 = num; } void display() { cerr<<"ptdl = "<<ptd1<<endl; } protected: int ptd1; static int Snum ; private: //A &a; int tst_var; }; class test2:public test1 { public: test2():a2(),a1(),test1(6) { cerr<<"test2 construcion\n"; a = 6; } void calc() { cerr<<"int test2\n"; } void Display() { cerr<<"snum is "<<Snum<<endl; } void anotherFun() { cerr<<"test2 anothre fun "<<a<<endl; } ~test2() { cerr<<"test2 deconstruction \n"; } protected: int a; ad1 a1; ad2 a2; };在main.cpptest1 t1; test2 *pt2 = static_cast<test2 *>(&t1); pt2->anotherFun();pt2->calc()pt2->anotherFun()的确调用了test2的函数,但是由于test2的对象没有定义所以cerr<<"test2 anothre fun "<<a<<endl; a的值为随机但是pt2->calc()却调用的是test1的函数可以这样理解,成员函数其实就是普通的函数,只是多传了一个this指针。(在调用pt2->anotherFun时,t1中没有这个函数,于是把本来是t1的this指针转化为t2的指针,就调用了t2的函数;
但是对于calc函数而言,t1有对应的实现,所以还是调用t1的calc
)
对于上面括号里的文字,要持保留意见,应该解释的不对。
pt2->anotherFun,既然pt2是test2的指针,那么就应该调用test2中的函数pt2->calc,因为calc是虚函数,所以要先查pt2所指对象的虚表,因为这个对象是test1的对象,所以其虚表中就是对应test1中函数。
如果在test1中calc不是虚函数的话,则pt2->calc将调用test2中的calc如果在main.cpp中是:test2 t2; test1 *rt1 = static_cast<test1 *>(&t2); rt1->calc(); rt1->anotherFun();对于rt1->calc()调用的是test2的函数,而rt1->anotherFun()却编译出错,这是因为在test1中没有anotherFun这个函数。更为详细的转换可以参考reinterpret_cast不检查任何类型,只是简单的将一个指针的值给另一个指针。http://www.vckbase.com/document/viewdoc/?id=1651本文讨论static_cast<> 和 reinterpret_cast<>。
介绍
大多程序员在学C++前都学过C,并且习惯于C风格(类型)转换。当写C++(程序)时,有时候我们在使用static_cast<>和reinterpret_cast<>时可能会有点模糊。在本文中,我将说明static_cast<>实际上做了什么,并且指出一些将会导致错误的情况。
泛型(Generic Types)
01.
float
f = 12.3;
02.
03.
float
* pf = &f;
04.
// static cast<>
05.
06.
// 成功编译, n = 12
07.
08.
int
n =
static_cast
(f);
09.
10.
// 错误,指向的类型是无关的(译注:即指针变量pf是float类型,现在要被转换为int类型)
11.
//int* pn = static_cast(pf);
12.
13.
//成功编译
14.
15.
void
* pv =
static_cast
(pf);
16.
17.
//成功编译, 但是 *pn2是无意义的内存(rubbish)
18.
19.
int
* pn2 =
static_cast
(pv);
20.