关于异常的概念:
一种程序控制机制,与函数机制独立互补。
设计的目的:
异常是冲着改变程序控制结构,以适应面对对象的程序而有效的工作。
关于异常的概念的部分代码:
#include
using namespace std;
int DDiv(int x, int y)
{
if (0 == y)
{
throw 0;
}
return x / y;
}
int Div(int x, int y)
{
/if (y == 0)
{
throw 0; //抛出一个整型
}
return x / y;/
int ret = DDiv(x, y); //异常跨越函数,可以继续向上抛出异常
return ret;
}
int main()
{
int a, b;
cin >> a >> b;
try
{
cout << Div(a, b) << endl;
}
catch (int)
{
cout << "被除数是0" << endl;
}
catch (char)
{
cout << "xxxxx" << endl;
}
return 0;
}
异常的语法:
1.若有异常,则通过throw操作创造一个异常对象并抛掷。
2.将可能出现的异常快嵌在try语句中,然后执行try语句保护段。
3.如果在try保护段没有发生异常,那么catch子句就不执行。程序从try快后跟随最后一个catch子句后面的语句继续执行下去。
4.catch子句跟在try后出现的顺序被检查。匹配的catch子句将捕获并处理异常。
5.如果匹配的处理器未找到,则运行函数terminate将被自动调用,
6处理不了的异常可以在catch的最后一个分支,使用throw语法往上扔。
7.异常机制与函数机制互不干涉。捕捉的方式就是基本类型的匹配。
8。异常捕捉严格按照类型匹配。
栈解旋的概念:异常被抛出后,从进入try快起,到异常被抛掷前,这期间在栈上的所有构造对象,都会被自动析构,析构的顺序与构造的顺序相反,这一过程称为栈的解旋。
栈解旋:
#include
using namespace std;
class Test
{
public:
Test()
{
cout << “Test构造函数” << endl;
}
~Test()
{
cout << "Test析构函数" << endl;
}
};
int Div(int x, int y)
{
if (0 == y)
{
throw 0; //一旦程序抛出异常, 从进入try起,到throw语句,栈上所有对象都被析构
}
return x / y;
}
int main()
{
int a, b;
cin >> a >> b;
try
{
Test t;
cout << Div(a, b) << endl;
cout << "12345" << endl;
}
catch(int)
{
cout << "zero exception" << endl;
}
cout << "helloworld" << endl;
return 0;
异常接口声明:
:
1.为了加强程序可读性,可以在函数声明中列出可能抛出的所有异常类型。
2.如果在函数声明中没有包含任何接口声明,则次函数可以抛掷任何类型的异常。如void func();
3.一个不抛掷任何类型异常的函数可以声明为:
void func() throw();
4.如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpected函数会被调用,该函数默认行为调用terminate函数中止程序。
#include
using namespace std;
//int Div(int x, int y); //函数Div可以抛出任意类型的异常
int Div(int x, int y) throw (int, char); //函数Div只能抛出int类型的异常
//int Div(int x, int y) throw(); //函数Div不会抛出异常
int main()
{
int a, b;
cin >> a >> b;
try
{
cout << Div(a, b) << endl;
}
catch (int)
{
cout << "被除数是0" << endl;
}
catch (char)
{
cout << "xxxxx" << endl;
}
return 0;
}
int Div(int x, int y) throw(int)
{
if (y == 0)
{
//throw 1.11; //抛出一个整型
throw 0;
}
return x / y;
}
异常的应用:
异常的层次结构:
1.异常是类-创造自己的异常类
2.异常派生
3.异常中的数据:数据成员
4.按引用传递异常
5.在异常中使用虚函数。
#include
using namespace std;
class array
{
private:
int length;
int *data;
public:
class eSize //内部类 抽象父类
{
protected:
const char *ErrMsg;
public:
eSize(const char *e)
{
ErrMsg = e;
}
virtual void printErr() = 0;
};
class eNegative : public eSize
{
public:
eNegative() : eSize("eNegative exception")
{
}
void printErr()
{
cout << ErrMsg << endl;
}
};
class eZero : public eSize
{
public:
eZero() : eSize("eZero exception")
{
}
void printErr()
{
cout << ErrMsg << endl;
}
};
class eTooSmall : public eSize
{
public:
eTooSmall() : eSize("eTooSmall exception")
{
}
void printErr()
{
cout << ErrMsg << endl;
}
};
class eTooBig : public eSize
{
public:
eTooBig() : eSize("eTooBig exception")
{
}
void printErr()
{
cout << ErrMsg << endl;
}
};
array(int l)
{
if (l < 0)
{
throw new eNegative;
}
else if (l == 0)
{
throw new eZero;
}
else if (l > 1000)
{
throw new eTooBig;
}
else if (l < 10)
{
throw new eTooSmall;
}
length = l;
data = new int[length];
}
};
int main()
{
try{
array a(10000);
}
catch(array::eSize *e)
{
e->printErr();
}
return 0;
}
输入输出流:部分操作
输入:
与iostream类库有关的头文件
iostream:包含了对输入输出流的进行操作的基本信息。
fstream:用于用户管理的I/O操作。
strstream:用于字符串流I/O。
stdiostream:用于混合使用C和C++的I/O机制。
iomanip:在使用格式化I/O时应该包含此文件。
在iostream中头文件中定义的流对象:
在iostream中头文件中定义的类有:ios,istream,ostream,iostream,istream_withassign,ostream_withassign,等
同时定义了4中流对象:cin,cout,cerr,clog。
标准输入流:
对象cin:
重点掌握的函数:
cin.get() //一次只能读取一个字符, 遇到EOF结束。
cin.get(一个参数) //读一个字符
cin.get(三个参数) //可以读字符串
cin.getline()
cin.ignore()
cin.peek()
cin.putback()
#include //输入(cin的一些操作)
using namespace std;
int main()
{
char ch;
char str[64] = {0};
int i = 0;
/*ch = cin.get(); //获取一个字符
cout << ch << endl;
while ((ch = cin.get()) != '\n')
{
str[i++] = ch;
}
cout << str << endl;*/
/*cin.get(ch);
cout << ch << endl;*/
/*cin.get(str, 8); //从标准输入获取8个字符放在str数组中
cout << str << endl;*/
/*cin.getline(str, 32); //获取一行数据,最多32个字节
cout << str << endl;*/
/*cin.ignore(5); //忽略前五个字节
cin >> str;
cout << str << endl;*/
/*ch = cin.peek(); //从标准输入读取一个字节,并且不清空标准输入
cout << ch << endl;
cin >> str;
cout << str << endl;*/
cin >> ch;
cout << ch << endl;
cin.putback(ch); //把ch写回标准输入
cin >> str;
cout << str << endl;
return 0;
}
输出:
标准输出流:
标准输出流对象cout
cout.flush()
cout.put()
cout.write()
cout.width()
cout.fill()
cout.setf()
manipulator(操作符,控制符)
fiush
endl
oct
dec
hex
setbase
setw
setfill
setprecision
#include
#include
using namespace std;
int main()
{
#if 0
//控制符方法控制输出格式
int a = 1000;
cout << a << endl;
cout << oct << a << endl; //8进制输出
cout << dec << a << endl; //10进制输出
cout << hex << a << endl; //16进制输出
char *str = "helloworld";
cout << setw(20) << str << endl;
cout << setfill('*') << setw(20) << str << endl;
double p = 222.00000 / 7.0000;
cout << p << endl;
cout << setprecision(3) << p << endl; //保留3位数字
cout << setiosflags(ios::scientific) << p << endl; //指数形式输出
#endif
//使用成员函数的方法
int a = 1000;
int b = 2000;
cout.unsetf(ios::dec); //先结束十进制输出
cout.setf(ios::oct); //再开始八进制输出
cout << a << endl;
cout.unsetf(ios::oct);
cout.setf(ios::hex);
cout << a << endl;
cout << b << endl;
char *str = "helloworld";
cout.width(20);
cout.setf(ios::left);
cout.fill('*');
cout << str << endl;
double p = 2222.00000 / 7.0000;
cout.precision(4);
cout << p << endl;
cout.setf(ios::scientific);
cout << p << endl;
cout.setf(ios::fixed);
cout << p << endl;
return 0;
}
文件操作:
#include
//#include //文件输入
//#include //文件输出
#include
using namespace std;
int main()
{
/ofstream ofs; //文件输出对象
if (!ofs.open(“hello.txt”))
{
cout << “打开失败” << endl;
}/
char *buf = "helloworld";
ofstream ofs("hello.txt");
ofs << buf;
ofs.close();
char str[32] = {0};
ifstream ifs("hello.txt");
ifs >> str;
cout << str << endl;
return 0;
}
const_cast.cpp:
#include
using namespace std;
int main()
{
const int a = 100;
int *p = const_cast
int &k = const_cast(a);
//int &b = 1; //用常量初始化普通引用 错误
const int &c = 1; //用常量初始化常引用
return 0;
}
dynamic_cast.cpp:
#include
using namespace std;
int main()
{
const int a = 100;
int *p = const_cast
int &k = const_cast(a);
//int &b = 1; //用常量初始化普通引用 错误
const int &c = 1; //用常量初始化常引用
return 0;
}
reinterprint.cpp;
#include
using namespace std;
int main()
{
int *a;
double b = 1.11;
a = reinterpret_cast(&b); //用于普通类型指针之间的转换,不安全
a = reinterpret_cast(0x100); //用于整数和指针之间的转换
return 0;
}
static_cast.cpp:
#include
using namespace std;
class Parent
{
private:
int a;
};
class Child : public Parent
{
private:
int b;
};
int main()
{
int a = 10;
float b = 1.11;
int *p;
a = static_cast(b); //用于基本类型之间的转换
//p = static_cast(&b); //不能用于基本类型指针之间的转换
Parent par;
Child ch;
par = static_cast(ch); //用于有继承关系的类之间的转换
Parent *p1 = static_cast(new Child); //用于有继承关系的类指针之间的转换
return 0;
}