📄 ex21.cpp
字号:
// 第21章 异常处理技术
// [例21.1] C++异常处理技术
# include <stdio.h>
long DivThrow(long x,long y)
{ if(y==0) throw x;
return x/y;
}
void ExceptHanding(long u,long v)
{ try
{ long d=DivThrow(u,v);
printf("ExceptHanding %d/%d=%d\n",u,v,d);
}
catch(long x)
{ printf("ExceptHanding=%d. Can't divided by zero\n",x); }
}
void main()
{ ExceptHanding(5,3); //输出结果ExceptHanding 5/3=1
ExceptHanding(5,0); //输出结果ExceptHanding=5. Can't divided by zero
}
//[例21.2]if语句加静态变量的跟踪
# include <stdio.h>
enum {NoZero=1,IsZero=1000};
static int sTrace=NoZero;
long DivideIf(long x,long y)
{ if(y==0){ sTrace=IsZero; return x; }
return x/y;
}
void TraceHanding(long u,long v)
{ long d=DivideIf(u,v);
switch(sTrace)
{ case NoZero: printf("TraceHanding %d/%d=%d\n",u,v,d);break;
case IsZero: printf("TraceHanding %d. Can't divided by zero\n",d);break;
}
}
void main()
{ TraceHanding(6,2); //输出结果TraceHanding 6/2=3
TraceHanding(2,0); //输出结果TraceHanding 2. Can't divided by zero
}
//[例21.3] 异常的多路捕获
# include <stdio.h>
enum enumType {eChars,eLong,eClass,eUnknown,eSkip};
class ClassE{};
struct Unknown{};
void PolyHanding(int kind)
{ if(kind==eSkip) throw eSkip; //这个throw语句匹配外层的try块
try
{ if(kind==eChars) throw "string type"; //
if(kind==eLong) throw (long)kind;
if(kind==eClass) throw ClassE(); //throw显式调用构造函数
if(kind==eUnknown) throw Unknown(); //调用缺省构造函数Unknown()
}
catch(char* s) { printf("Except Handler is=%s\t",s);}
catch(long) { printf("Except Handler is long type\t");}
catch(ClassE) { printf("Except Handler is ClassE type\t");}
catch(...) { printf("Except Handler is Unknown type\t"); }
printf("Embeded try~catch block is not skip\n");
}
void main()
{ try
{ PolyHanding(eChars); //程序内部的异常在内部有效处理
PolyHanding(eLong); //流程依次执行函数调用
PolyHanding(eClass);
PolyHanding(eUnknown); //程序内部的异常在内部有效处理
PolyHanding(eSkip); //函数调用引发外层try块的throw语句
PolyHanding(eLong); //这两个函数调用是程序的死码区
PolyHanding(eClass);
}
catch(enumType) //拦截梅举类enumType的异常流
{ printf("Embeded try~catch block is skipped\n"); }
printf("this printf is a must route\n"); //这个printf语句是流程的必由之路
} //输出如下:
//[例21.4] 异常的重新抛出
# include <stdio.h>
enum {eLong,eUnknown,eSpecial};
struct Unknown{};
class Special{};
void fa(int kind)
{ try {
if(kind==eSpecial) throw Special();
if(kind==eUnknown) throw Unknown();
}
catch(Special) { printf("fa Rethrowing Special Exception out\n");
throw; //相当于 throw Special()到上层fb的 catch(Special)入口
}
catch(...) { printf("fa Rethrowing Unknown Exception out\n");
throw; //相当于throw Unknown()到上层fb的catch(...)
}
printf("normal process in fa\t");
}
void fb(int kind)
{ try { fa(kind);}
catch(Special)
{ printf("fb Rethrowing Special Exception out\n");
throw; //相当于 throw Special()到上层fc的 catch(Special)入口
}
catch(...) { printf("Unknown Exception treated here in fb\n");}
printf("normal process in fb\n");
}
void fc(int kind)
{ try
{ fb(kind);
if(kind==eLong) throw (long)kind;
}
catch(long) { printf("long type Exception is in fc \n");}
catch(Special) { printf("Special Exception is treated here in fc \n");}
}
void main() { fc(eLong); fc(eUnknown); fc(eSpecial); }
//[例21.5]异常过程中对象的清除
#include<stdio.h>
class ClassB
{ public: int m_b;
ClassB(int n=1) {m_b=n;printf("%d.ClassB::ClassB(),this=%p\n",m_b,this);}
~ClassB() { printf("%d.ClassB::~ClassB()\n",m_b);}
};
class ClassC
{ public: int m_c;
ClassC(int n=2) {m_c=n;printf("%d.ClassC::ClassC(),this=%p\n",m_c,this);}
~ClassC() { printf("%d.ClassC::~ClassC()\n",m_c); }
void Show() { printf("Show m_c=%d,this=%p \n",m_c,this); }
};
enum {eObjc=888,eObjh=3};
void fa(int k)
{ if(k==eObjc) {
printf("send local Objc with k=%d\n",eObjc);
throw ClassC(k); //直接抛出一个无名对象
}
ClassB objb(2); //中间定义一个局部对象objb2
ClassC *pObjc=new ClassC(k); //定义一个Heap空间的对象
printf("send Heap obj with k=%d\n",k);
throw pObjc; //无过滤条件的抛出对象指针
printf("this code area is dead block\n"); //死码区
delete pObjc;
}
void fb(int k)
{ printf("Enter regular routine with k=%d\n",k);
try{ ClassB objb(1); //定义局部变量objb1
fa(k);
}
catch(ClassC objc ) //接受数值对象的入口处理器
{ printf("local Objc received\n");
objc.Show();
}
catch(ClassC *p=NULL ) //接受对象指针的入口处理器
{ if(p!=NULL)
{ printf("Heap Obj received\n");
p->Show();
delete p;
}
}
}
void main() { fb(eObjc); fb(eObjh); }
//[例21.6]继承层次catch处理器的先后次序
#include<stdio.h>
class B
{ public: int m_b;
B (int n=1) {m_b=n;printf("B::B()this=%p\n",this);}
virtual ~B (){printf("B::~B()this=%p\n",this);}
virtual int HandleError();
};
class C : public B
{ public: int m_c;
C() {m_c=2;printf("C::C()this=%p\n",this);}
virtual ~C(){printf("C::~C()this=%p\n",this);}
virtual int HandleError();
};
class D : public C
{ public: int m_d;
D(){m_d=4; printf("D::D()this=%p\n",this);}
virtual ~D(){printf("D::~D()this=%p\n",this);}
virtual int HandleError();
};
int B::HandleError() {printf("B::HandleError()this=%p\n",this);return 1;}
int C::HandleError() {printf("C::HandleError()this=%p\n",this);return 0;}
int D::HandleError() {printf("D::HandleError()this=%p\n",this);return 1;}
enum{classb,classc,classd,etype1,etype2};
int ErrorInfo(int k) //对错误消息进行分流的函数
{ switch(k)
{ case etype1: return etype1;
case etype2: return etype2;
default : return etype2+1;
}
}
void ThrowHandler(int k)
{ switch(k) //throw的表达式先完成副作用
{ case classb: throw B(); //抛出基类的无名对象
case classc: throw C(); //抛出直接派生类对象
case classd: throw D(); //抛出间接派生类对象
default : throw ErrorInfo(k); //抛出其它错误消息
}
}
void VirtualHandling(int k)
{ try {ThrowHandler(k); } //抛出两种类型的异常
catch(B & rBase) { //基对象的引用形参
rBase.HandleError(); //对象别名虚拟调用虚函数
}
catch(int k) //捕获整型数值类型消息
{ switch(k) //消息根据具体的数值分流
{ case etype1: printf("etype1 Error treated here\n");break;
case etype2: printf("etype2 Error treated here\n");break;
default: printf("a type Error treated here\n");break;
}
}
}
void DerivedFirst(int k)
{ try {ThrowHandler(k);}
//catch(B b){b.HandleError();} //警告'class D' : is caught by base class ('class B ')
catch(D d) {d.HandleError();} //间接派生类对象数值形参catch块置于前面
catch(C c) {c.HandleError();} //直接派生类对象数值形参catch块置于中间
catch(B b) {b.HandleError();} //基类对象数值形参catch块置于最后
catch(int ) { printf("a int Error treated here\n"); }
}
void main()
{ ////VirtualHandling(etype2+7);输出结果a type Error treated here
VirtualHandling(classd); DerivedFirst(classc);
}
318
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -