[C/C++]_[初级]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和区别]

Posted infoworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C/C++]_[初级]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和区别]相关的知识,希望对你有一定的参考价值。


场景:

1. C++的对象区别于C的原因是他们可以有继承关系, 方法有重载, 覆盖关系等, 他们的对象内存数据结构因此也比较复杂.

2. 很多情况下我们需要一个父类来存储子类的指针对象进行通用方法的操作,涉及到具体某个子类对象特定操作时又需要强制转换为子类,那么这时候该用什么好呢?

答: 如果不需要类型检查的话就直接用C的强制转换即可(B*)c. 但是C++ 之父并不推荐使用C的强制类型转换;

原因1是没有编译器检查.

原因2是对象指针在子类父类之间转换时所对应的地址值可能会变化, 这样用C的转换会有误导的可能在那里.


看例子和注释说明吧:

test.cpp

#include <iostream>

class A
{
public:
	A(){}
	~A(){}
	int i;
	int j1;
	void Test(){ std::cout << "TestA" << std::endl;}
	/* data */
};

class C
{
public:
	C(){}
	~C(){}
	int j;
	void Test(){ std::cout << "TestC" << std::endl;}
	/* data */
};

class B : public A,public C
{
public:
	B(){}
	~B(){}
	void Test(){ std::cout << "TestB" << std::endl;}
	/* data */
};

class K
{

};

// static_cast: 可以进行类型上行和下行转换,会进行类型检查.
// reinterpret_cast: 和C的强转一样,不做类型检查,可以从任意类型转换为其他类型.
// dynimic_cast:  只适用于多态的类(带virtual)
int main(int argc, char const *argv[])
{
	A* a = new A();
	B* b = new B();
	C* c = b;

	std::cout << "(int*)a* :" << (int*)a << " (int)a:" << (int)a << " reinterpret_cast<int>(a):" 
		      << reinterpret_cast<int>(a) << std::endl;

	std::cout << "(int*)b :" << (int*)b << " (int)b:" << (int)b << " reinterpret_cast<int>(b):" 
		      << reinterpret_cast<int>(b) << std::endl;

	// 1.这里如果把c转换为(K*)c,编译不会报错,但是如果使用static_cast<K*>编译会报错.
	// 因为static_cast会进行上行的类型检查.
    // 注意: 这里(int*)c的地址和上边的(int*)b地址是不一样的,因为他们不是多态关系,而且A,C有成员变量,因此会有偏移量.(没有virtual)
	std::cout << "(int*)c :" << (int*)c << " (int)c:" << (int)c << " reinterpret_cast<int>(c):" 
		      << reinterpret_cast<int>(c) <<  " (B*)c: " << (B*)c << " static_cast<B*>(c):" 
		      << static_cast<B*>(c) << " static_cast<C*>(b):" 
		      << static_cast<C*>(b)
		      << std::endl;

    // 以下编译会报错,dynimc_cast不允许非多态转换,因为没有virtual
	// ////error: cannot dynamic_cast ‘c‘ (of type ‘class C*‘) to type ‘class B*‘ (source type is not polymorphic)
	// 如果C的构造函数加virtual的话是可以转的,而且带virtual表的地址不会变.
	// std::cout << "c* :" << (int*)c << ":" << (int)c << ":" 
	// 	      << dynamic_cast<B*>(c) << ":"
	// 	      << std::endl;	      
	return 0;
}

输出:

(int*)a* :0x2c64e0 (int)a:2909408 reinterpret_cast<int>(a):2909408
(int*)b :0x2c2378 (int)b:2892664 reinterpret_cast<int>(b):2892664
(int*)c :0x2c2380 (int)c:2892672 reinterpret_cast<int>(c):2892672 (B*)c: 0x2c2378 static_cast<B*>(c):0x2c2378 static_cast<C*>(b):0x2c2380

所以你看到以下static_cast的用法不要觉得奇怪, 它是为了使用编译器检查.

    template<typename T> void** IID_PPV_ARGS_Helper(T** pp) 
    {
        static_cast<IUnknown*>(*pp);    // make sure everyone derives from IUnknown
        return reinterpret_cast<void**>(pp);
    }



参考:

http://www.cnblogs.com/chio/archive/2007/07/18/822389.html



以上是关于[C/C++]_[初级]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和区别]的主要内容,如果未能解决你的问题,请参考以下文章

[C/C++]_[中级]_[static_cast的详细解析]

[C/C++]_[中级]_[static_cast的详细解析]

[C/C++11语法]_[初级]_[lamba 表达式介绍]

[C/C++20]_[初级]_[信号量semaphore]

[C/C++11]_[初级]_[使用正则表达式库regex]

[C/C++]_[初级]_[声明和使用字符串常量和字节常量]