C++强制转换之static_cast
2016-04-19 23:43
736 查看
static_cast
用法:static_cast<type-id>(expression)
简介:该运算符把expression转换为type_id类型,但没有运行时类型检查来保证转换的安全性。
主要有以下几种用法:
1. 用于类层次结构中基类和派生类之间指针或引用的转换:进行上行转换是安全的,进行下行转换时是不安全的
2. 用于基本数据类型之间的转换
3. 把空指针转换成目标类型的空指针
4. 把任何类型的表达斯转化成void型
下面给出一些具体的示例
例子1
分析:B继承自A,B类型可以上行转换为A类型
例子2
分析:B虽然继承自A,但A不能强转为B
例子3
结果如下:
分析:理所当然,指针的上行转换不会出错
例子4
分析:本例中指针pb会有一个vptr,但指向的位置并不是类B的虚表(pb中的vptr并不指向任何虚表,如果A中有虚函数的话,vptr会指向A的虚表),找不到对应虚函数,所以自然会崩溃
例子5
分析:转化不会出错,具体原因跟类的对象的内存模型有关,这里不做解释,另外,如果在类A中加个随便加个虚函数,pa和pb将会相同,另外,无论怎么转换,vptr永远指向类B的虚表。
例子6
结果,编译通过运行成功
结果,编译出错,error C2243: “static_cast”: 从“D *”到“C *”的转换存在,但无法访问
如果有两个类A和B,两者不存在继承关系,它们之间无法通过static_cast进行转换,代码就不上了
例子7
#include <stdio.h>
#include <string>
using namespace std;
class A
{
public:
A(int i) : m_a(i)
{
}
~A()
{
printf("A destruction\n");
}
private:
int m_a;
};
int main(int argc, char** argv)
{
A* a = new A(1);
void* v = static_cast<void*>(a);
a = static_cast<A*>(v);
int* p = static_cast<int*>(v);
delete a;
getchar();
return 0;
}
编译通过运行成功,static_cast可以将void*型转换为任意类型,dynamic_cast则不行,void*类型不能作为括号中的参数
用法:static_cast<type-id>(expression)
简介:该运算符把expression转换为type_id类型,但没有运行时类型检查来保证转换的安全性。
主要有以下几种用法:
1. 用于类层次结构中基类和派生类之间指针或引用的转换:进行上行转换是安全的,进行下行转换时是不安全的
2. 用于基本数据类型之间的转换
3. 把空指针转换成目标类型的空指针
4. 把任何类型的表达斯转化成void型
下面给出一些具体的示例
例子1
#include <stdio.h> #include <string> using namespace std; class A { public: A(int i) : m_a(i) { } void Print() { } private: int m_a; }; class B : public A { public: B() : A(1) { } virtual ~B() {} virtual void Test() { printf("Test\n"); } }; int main(int argc, char** argv) { B b; A a = static_cast<A>(b); a.Print(); getchar(); return 0; }运行结果如下:
m_a: 1
分析:B继承自A,B类型可以上行转换为A类型
例子2
A a = A(1); B b = static_cast<B>(a); //错误,error C2440: “static_cast”: 无法从“A”转换为“B”,无构造函数可以接受源类型,或构造函数重载决策不明确
分析:B虽然继承自A,但A不能强转为B
例子3
#include <stdio.h> #include <string> using namespace std; class A { public: A(int i) : m_a(i) { } void Print() { printf("m_a: %d\n", *((int*)this)); } A(const A& a) { this->m_a = a.m_a; } ~A() {} private: int m_a; }; class B : public A { public: B() : A(1) { } virtual ~B() {} virtual void Test() { printf("Test\n"); } }; int main(int argc, char** argv) { B* pb = new B(); A* pa = static_cast<A*>(pb); pa->Print(); getchar(); return 0; }
结果如下:
m_a: 1
分析:理所当然,指针的上行转换不会出错
例子4
#include <stdio.h> #include <string> using namespace std; class A { public: A(int i) : m_a(i) { } void Print() { printf("m_a: %d\n", *((int*)this)); } A(const A& a) { this->m_a = a.m_a; } ~A() {} private: int m_a; }; class B : public A { public: B() : A(1) { } virtual ~B() {} virtual void Test() { printf("Test\n"); } }; int main(int argc, char** argv) { A* pa = new A(1); B* pb = static_cast<B*>(pa); pb->Test(); getchar(); return 0; }结果:可以运行,但是运行执行到Test时会崩溃
分析:本例中指针pb会有一个vptr,但指向的位置并不是类B的虚表(pb中的vptr并不指向任何虚表,如果A中有虚函数的话,vptr会指向A的虚表),找不到对应虚函数,所以自然会崩溃
例子5
#include <stdio.h> #include <string> using namespace std; class A { public: A(int i) : m_a(i) { } void Print() { printf("m_a: %d\n", *((int*)this)); } A(const A& a) { this->m_a = a.m_a; } ~A() {} private: int m_a; }; class B : public A { public: B() : A(1) { } virtual ~B() {} virtual void Test() { printf("Test\n"); } }; int main(int argc, char** argv) { B* pb = new B; A* pa = static_cast<A*>(pb); printf("pa: %p, pb: %p\n", pa, pb); pb = static_cast<B*>(pa); printf("pa: %p, pb: %p\n", pa, pb); pb->Test(); getchar(); return 0; }运行结果如下:
pa: 0051B434, pb: 0051B430 pa: 0051B434, pb: 0051B430 Test
分析:转化不会出错,具体原因跟类的对象的内存模型有关,这里不做解释,另外,如果在类A中加个随便加个虚函数,pa和pb将会相同,另外,无论怎么转换,vptr永远指向类B的虚表。
例子6
class C { }; class D: public C { }; int main(int argc, char** argv) { D* d = new C(); C* c = static_cast<C*>(d); getchar(); return 0; }
结果,编译通过运行成功
class C { }; class D: protected C { }; int main(int argc, char** argv) { D* d = new D(); C* c = static_cast<C*>(d); getchar(); return 0; }
结果,编译出错,error C2243: “static_cast”: 从“D *”到“C *”的转换存在,但无法访问
class C { }; class D: private C { }; int main(int argc, char** argv) { D* d = new D(); C* c = static_cast<C*>(d); getchar(); return 0; }结果,编译出错,error C2243: “static_cast”: 从“D *”到“C *”的转换存在,但无法访问
如果有两个类A和B,两者不存在继承关系,它们之间无法通过static_cast进行转换,代码就不上了
例子7
#include <stdio.h>
#include <string>
using namespace std;
class A
{
public:
A(int i) : m_a(i)
{
}
~A()
{
printf("A destruction\n");
}
private:
int m_a;
};
int main(int argc, char** argv)
{
A* a = new A(1);
void* v = static_cast<void*>(a);
a = static_cast<A*>(v);
int* p = static_cast<int*>(v);
delete a;
getchar();
return 0;
}
编译通过运行成功,static_cast可以将void*型转换为任意类型,dynamic_cast则不行,void*类型不能作为括号中的参数
相关文章推荐
- C++学习笔记58——模板实参推断
- C++ 中Traits技术 (5) —— 关于STL中对迭代器封装的类型介绍
- c++ 遍历文件夹及其子文件夹
- C++友元函数重载"++"和"--"运算符
- C++常用库
- C语言计算字符串长度的几种方法
- Next Permutation
- C语言基本数据类型
- 探究fork函数
- C语言运算符表达式
- 巩固C语言(十二)----文件加解密
- C++重载括号和重载类型探索
- day01 C语言基础
- C++ 的内置函数(inline)和作用域运算符(::)
- 浅析C++多态及其实现模式
- 细谈C++的运算符重载
- C++第四次实验
- C++深层复制解决指针悬挂
- 【代码】C++实现广义表及其测试用例
- C语言文件操作包括static,extern的学习笔记