C++强制转换之static_cast

static_cast

用法: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*类型不能作为括号中的参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值