一 名称和语法
1 C语言风格:不管什么类型的转换统统是:
TYPE b = (TYPE)a;
2 C++风格:
1)static_cast,静态类型转换。如int转换成char
2)reinterpreter_cast,重新解释类型
3) dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多态类型转换,运行时进行类型识别,把父类转换成子类。
4)const_cast,字面上理解就是去const属性
void main01()
{
double dpi = 3.1415926;
int num1 = (int)dpi; //C类型转换
int num2 = static_cast<int>(dpi); //静态类型转换 编译的时c++编译器会做类型检查
int num3 = dpi; //c语言中 隐式类型转换的地方 均可使用 static_cast<>() 进行类型转换
char *p1 = "hello...itcast ";
int *p2 = NULL;
//p2 = static_cast<int*>(p1); // 使用static_cast, 编译器编译时,会做类型检查 若有错误 提示错误
p2 = reinterpret_cast<int *>(p1); //若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释
cout << "p1:" << p1 << endl; //%s指针指向的内存空间
cout <<"p2" << p2 << endl; //%d 指针首地址
//总结:通过 reinterpret_cast<>() 和 static_cast<>()把C语言的强制类型转换 都覆盖了..
cout<<"hello..."<<endl;
system("pause");
return ;
class Animal
{
public:
virtual void cry() = 0;
};
class Dog : public Animal
{
public:
virtual void cry()
{
cout << "汪汪" << endl;
}
void doHome()
{
cout << "看家" << endl;
}
};
class Cat : public Animal
{
public:
virtual void cry()
{
cout << "喵喵" << endl;
}
void doThing()
{
cout << "抓老鼠" << endl;
}
};
void playObj(Animal *base)
{
base->cry(); // 1有继承 2虚函数重写 3 父类指针 指向子类对象 ==>多态
//需求:在这里能识别子类对象
// dynamic_cast 运行时类型识别 RIIT
Dog *pDog = dynamic_cast<Dog *>(base);
if (pDog != NULL)//转换失败返回NULL
{
pDog->doHome(); //让够 做自己 特有的工作
}
Cat *pCat = dynamic_cast<Cat *>(base); //父类对象 ===> 子类对象
//向下转型
//把老子 转成 小子
if (pCat != NULL)
{
pCat->doThing(); //让够 做自己 特有的工作
}
}
void main()
{
Dog d1;
Cat c1;
Animal *pBase = NULL;
pBase = &d1;
playObj(&d1);
playObj(&c1);
system("pause");
}
#include <iostream>
using namespace std;
//const char *p 的const修饰 让p指向的内存空间 变成只读属性
void printBuf(const char * p)
{
p1 = const_cast<char *>(p);//由const char * 转换成char*
p1[0] = 'Z' ; //通过p1 去修改了内存空间
cout << p << endl;
}
void main()
{
char buf[] = "aaaaaaaaafffffddd";
char *myp = "aaaaaaaaafffffddd";//此时*myp指向的内存空间时常量,不可修改。
//程序员 要确保 p所指向的内存空间 确实能修改 ;如果不能修改会带来灾难性后果
//printBuf (buf);
printBuf (myp);
system("pause");
}
二 异常处理
1 基本思想
1) C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中
2)异常是专门针对抽象编程中的一系列错误处理的
3)异常超脱于函数机制,决定了其对函数的跨越式回跳。
4)异常跨越函数
2 基本语法
1)思想
a)若有异常则通过throw操作创建一个异常对象并抛掷。
b)将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。
c)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去。
d)catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛掷异常)。
e)如果匹配的处理器未找到,则运行函数terminate将被自动调用,其缺省功能是调用abort终止程序。(程序down)
f)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔。
g)异常机制与函数机制互不干涉,但捕捉的方式是基于类型匹配。
捕捉相当于函数返回类型的匹配,而不是函数参数的匹配,所以捕捉不用考虑一个抛掷中的多种数据类型匹配问题
h)异常捕捉严格按照类型匹配
int divide(int x, int y ) //抛异常
{
if (y ==0)
{
throw x; //如果执行了抛出,则后面的代码不再执行
}
return x/y;
}
void main() //接异常
{
try
{
cout << "8/2 = " << divide(8, 2) << endl; ///调用
cout << "10/0 =" << divide(10, 0) << endl;
}
catch (int e) //捕捉到上面的异常,同一类型
{
cout << "e" << " is divided by zero!" << endl;
}
catch(...)
{
cout << "其他未知异常" << endl;
}
cout << "ok" << endl;
system("pause");
return ;
}
三 栈解旋(unwinding)
1 定义:异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反。这一过程称为栈的解旋(unwinding)。
#include <iostream>
using namespace std;
class Test3
{
public:
Test3(int a=0, int b=0)
{
this->a = a;
this->b = b;
cout << "构造函数do \n";
}
~Test3()
{
cout << "析构函数do \n";
}
private:
int a;
int b;
};
void myDivide() throw (int, char, char *)
{
Test3 t1(1, 2), t2(3, 4);
cout << "myDivide ...要发生异常\n" ;
throw 1;
}
void main()
{
try
{
myDivide();
}
catch (int a)
{
cout << "int类型 异常\n" ;
}
catch (...)
{
cout << " 未知 异常\n" ;
}
cout<<"hello..."<<endl;
system("pause");
return ;
}
四异常接口声明
1 为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常类型,例如: void func() throw (A, B, C , D); //函数func()能够且只能抛出类型A B C D及其子类型的异常。
2 如果在函数声明中没有包含异常接口声明,则此函数可以抛掷任何类型的异常,例如:void func();
3 一个不抛掷任何类型异常的函数可以声明为:
void func() throw();
4 如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpected函数会被调用,该函数默认行为调用terminate函数中止程序
五 异常类型及生命周期
1 接受元素时使用异常变量,则进行拷贝构造
2 使用引用的话,catch的是throw的那个对象
3 指针和引用/元素可同时出现,但引用和元素不能同时现如果是指针必须throw的是一个地址(new 申请内存)
结论:用引用是最好的
六 标准程序库异常
C++标准提供了一组标准异常类,这些类以基类exception开始,
标准程序库抛出的所有异常,都派生于该基类。
1 案例
// out_of_range
#include "iostream"
using namespace std;
#include <stdexcept>
#include "string"
// out_of_range
class Teacher
{
public:
Teacher(int age)
{
if (age > 100)
{
string s = "年龄太大";
throw out_of_range(s);
}
this->age = age;
}
protected:
private:
int age;
};
void main61()
{
try
{
Teacher t1(102);
}
catch (out_of_range e)
{
cout << e.what() << endl;
}
exception e;
system("pause");
}
class MyException : public exception
{
public:
MyException(const char *p)
{
this->m_p = p;
}
virtual const char * what()
{
cout << "MyException: 类型" << m_p << endl;
return m_p;
}
protected:
private:
const char *m_p;
};
void testMyExcept()
{
throw MyException("函数异常");
}
void main()
{
try
{
testMyExcept();
}
catch (MyException & e)
{
e.what();
}
catch (...)
{
cout << "未知 类型 " << endl;
}
system("pause");
}