现在的位置: 首页 > 综合 > 正文

static_const和reinterpret_cast

2013年12月02日 ⁄ 综合 ⁄ 共 3070字 ⁄ 字号 评论关闭

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.cpp
test1 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.
【上篇】
【下篇】

抱歉!评论已关闭.