1.类型转换
#include<iostream>
using namespace std;
void main()
{
double pai = 3.1415926;
int num01 = pai;//c语言的隐式类型转换;
int num03 = static_cast<int>(pai);//c语言中的隐式类型转换 均可使用static_cast<>进行转换;
int num02 = (int)pai;//显示类型转换
cout << num02 << endl;
char* p = "hello...C++";
int* i = NULL;
i =reinterpret_cast<int *> (p);//如果不同类型之间进行类型转换的时候,需要使用reinterpret_cast<>;
cout << i << endl;//相当于打印的%d;
cout << p << endl;//打印的是%s;
system("pause");
}
对象进行类型转换:
#include<iostream>
using namespace std;
class Anima
{
public:
virtual void eat()
{
cout << "动物吃饭" << endl;
}
};
class Dog : public Anima
{
public :
void kanmen()
{
cout << "狗看门" << endl;
}
};
void test(Anima * a)
{
//这种转型必须条件是有虚函数,发生多态;
Dog* dd = dynamic_cast<Dog*>(a);
dd->eat();
dd->kanmen();
Dog* dd2 = reinterpret_cast<Dog*>(a);//强制类型转换,类型从新解释;
dd2->eat();
dd2->kanmen();
//编译进行类型检查,Anima和Dog是一个家族的可以转换;
//如果在定义个Tree类对象,使用static_cast进行tree转换成dog就会报错;
Dog* dd3 = static_cast<Dog*>(a);
dd3->eat();
dd3->kanmen();
}
void main()
{
double pai = 3.1415926;
int num01 = pai;//c语言的隐式类型转换;
//c语言中的隐式类型转换 均可使用static_cast<>进行转换;在编译的时候进行类型检查;
int num03 = static_cast<int>(pai);
int num02 = (int)pai;//显示类型转换
cout << num02 << endl;
char* p = "hello...C++";
int* i = NULL;
i =reinterpret_cast<int *> (p);//如果不同类型之间进行类型转换的时候,需要使用reinterpret_cast<>;
cout << i << endl;//相当于打印的%d;
cout << p << endl;//打印的是%s;
//当子父类之间进行类型转换的时候:dynamic_cast;
Dog d;
test(&d);
system("pause");
}
const_cast:的使用
#include<iostream>
using namespace std;
void test(const char* p)
{
//将只能读的指针转换成可以读写的指针;
char* m = const_cast<char *>(p);
m[0] = 'Z';
cout << m << endl;
}
void main()
{
//将常量区的字符串拷贝到栈区,动态分配内存;
char c[] = "abcdefghijklmnopqrstuvwxyz";
test(c);
//这个是一个指针直接指向一个常量区的字符串;不能修改的;
//char* mm= "abcdefghijklmnopqrstuvwxyz";
//test(mm);//这样就会报错;
system("pause");
}
结论:程序员要清楚的知道:要转换的变量,类型转换之前和之后的类型,转后的后果是什么;
一般情况下不建议类型转换,避免类型转换;
2.C++中的异常:
#include<iostream>
using namespace std;
//返回int类型的异常
void copychar(const char* str1, char* str2)
{
if (str1==NULL)
{
throw 1;
}
if (str2 == NULL)
{
throw 2;
}
if (*str1 == 'z')
{
throw 3;
}
while (*str1 !='\0')
{
*str2 = *str1;
str1++;
str2++;
}
*str2 = '\0';
}
//抛出char* 类型的异常;
void copychar2(const char* str1, char* str2)
{
if (str1 == NULL)
{
throw "str1 = null";
}
if (str2 == NULL)
{
throw "str2 = null";
}
if (*str1 == 'z')
{
throw "拷贝过程中出错了";
}
while (*str1 != '\0')
{
*str2 = *str1;
str1++;
str2++;
}
*str2 = '\0';
}
class Str1 {};
class Str2 {};
class CopyErr {};
//抛出对象 类型的异常;
void copychar2(const char* str1, char* str2)
{
if (str1 == NULL)
{
throw Str1();
}
if (str2 == NULL)
{
throw Str2();
}
if (*str1 == 'z')
{
throw CopyErr();
}
while (*str1 != '\0')
{
*str2 = *str1;
str1++;
str2++;
}
*str2 = '\0';
}
void main()
{
char str[] = "zbcdefg";
char str2[500];
try
{
//copychar(str,str2);
copychar2(str, str2);
}
catch (int e)//e可以写也可以不写,就看你用不用这个e;
{
cout << e << "int 类型数据异常" << endl;
}
catch (char* c)
{
//char* c所指向的内存空间是在throw的时候分配的内存的;
cout << c << "char* 类型数据异常" << endl;
}
//-----------
catch (Str1 s)
{
//这种是将匿名对象拷贝给s的;
cout << "Str1 类型数据异常" << endl;
}
catch (Str2* s2)
{
//这种情况就接受不到异常了,上面发的是对象异常,这里用指针接受不到的;会调到位置异常中去;
//异常时严格的按照类型匹配的,如果非要用指针接的话,throw的时候必须抛出一个地址,
//但是还不能是内名对象,因为会被析构掉,成为野指针,必须是new出来的对象;new的实在堆中分配的内存,需要手动许释放内存的;
cout << "Str2 类型数据异常" << endl;
}
catch (CopyErr& cs)
{
//这种事将对象直接扔过的;所以在抛出一个对象异常的时候,使用引用接受是最好的;
cout << "CopyErr 类型数据异常" << endl;
}
//-----------
catch (...)
{
cout << "位置 类型数据异常" << endl;
}
system("pause");
}