Day35.C++09
01.类型转换-静态类型和动态转换和常量转换
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//静态转换
//基础类型
void test01()
{
char a = 'a';
double d = static_cast<double>(a);
cout << "d = " << d << endl;
}
//父子之间的转换
class Base{};
class Child :public Base{};
class Other{};
void test02()
{
Base* base = NULL;
Child* child = NULL;
//把base*转为Child* 类型,向下,不安全
Child* child2 = static_cast<Child*>(base);
//把Child*转为base* 类型,向上,安全
Base* base2 = static_cast<Base*>(child);
//转Other*类型 类Other与类Base之间不存在父子关系,不可以转换类型
//Other* other = static_cast<Other*>(base);
}
//static_cast 的使用 static_cast<目标类型>(原始对象)
//动态转换
void test03()
{
//基础类型不可以动态转换
char c = 'a';
//dynamic_cast 非常严格 ,失去精度或者 不安全,都不可以转换
//double d = dynamic_cast<double>(c);
}
class Base2 {
virtual void func() {}
};
class Child2:public Base2{
virtual void func() {}
};
class Other2 {};
void test04()
{
Base2* base = NULL;
Child2* child = NULL;
//Child*转Base* 安全
Base2* base2 = dynamic_cast<Base2*>(child);
//Base*转Child* 不安全
//Child2* child2 = dynamic_cast<Child2*>(base);
//如果发生了多态,那么可以让基类转为派生类,向下转换
Base2* base3 = new Child2;
Child2* child3 = dynamic_cast<Child2*>(base3);
}
//常量转换(const_cast)
void test05()
{
const int* p = NULL;
//去除const
int* newP = const_cast<int*>(p);
int* p2 = NULL;
const int* newP2 = const_cast<const int*>(p2);
//不能对非指针 或者 非引用的变量进行转换
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
02.异常的基本处理
总结:
try 试图执行 try{} 中的内容
在可能出现已成的地方 抛出异常 throw
try下面 catch 捕获异常
catch(捕获类型) ...代表 所有其他的类型
如果不想处理异常,继续向上抛出,throw
如果没有任何处理异常的地方,那么程序调用terminate函数中断程序
自定义异常类,可以抛出自定义的对象,捕获自定义的异常
从try开始,到throw抛出异常之前,所有栈上的对象,都会被释放,这个过程为栈解旋
异常的接口声明:如果想抛出特定的类型异常,可以利用异常的接口声明
void func() throw(int,char){} //只能抛出int 或者 char 类型的异常
void func() throw(){} //不抛出任何类型的异常
代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class myException//自定义异常类
{
public:
void printError()
{
cout << "自定义的异常" << endl;
}
};
int myDevide(int a, int b)
{
if (b == 0)
{
//throw -1;//抛出int类型异常,异常必须处理,如果不处理,就会挂掉
//throw 3.14;
//栈解旋
//从try开始,到throw抛出异常之前,所有栈上的对象,都会被释放,这个过程为栈解旋
throw myException();
}
return a / b;
}
void test01()
{
int a = 10;
int b = 0;
try
{
cout << myDevide(a, b) << endl;
}
catch (int)
{
cout << "int类型异常捕获" << endl;
cout << "除数为0,无解" << endl;
}
catch (double)
{
throw;
cout << "double类型异常捕获" << endl;
cout << "除数为0,无解" << endl;
}
catch (myException e)
{
e.printError();
}
catch (...)
{
cout << "其他类型异常捕获" << endl;
}
}
int main(void)
{
try
{
test01();
}
catch (double)
{
cout << "main函数中 double类型异常捕获!" << endl;
}
system("pause");
return EXIT_SUCCESS;
}
03.异常变量生命周期
- 如果MyException e,会多开销一份数据,调用拷贝构造
- 如果MyException* e ,不new 提前释放对象,new 的话需要自己管理 delete
- 推荐MyException& e,容易些,而且不会创建多余的数据
04.使用系统提供的标准异常
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<stdexcept>
#include<string>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
if (age < 0 || age>200)
{
//抛出越界异常
throw out_of_range("年龄越界了!");
}
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
Person p("孙猴子", 500);
}
int main(void)
{
try
{
test01();
}
catch (out_of_range& e)
{
cout << e.what() << endl;
}
system("pause");
return EXIT_SUCCESS;
}
05.自己编写异常类
总结:
- 自己的异常类 , 需要继承于 exception
- 需要重写 虚析构 和 what()
- 内部维护一个错误信息字符串
- 构造时候传入 错误信息字符串 ,what()返回 错误信息字符串
- string 转 char* c_str()
代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
class myOutOfRangeException :public exception
{
public:
myOutOfRangeException(string errorInfo)
{
this->m_ErrorInfo = errorInfo;
}
virtual ~myOutOfRangeException()
{
}
virtual const char* what() const
{
//返回 错误信息
//string 转char* c_str()
return this->m_ErrorInfo.c_str();
}
string m_ErrorInfo;
};
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
if (age < 0 || age>200)
{
//抛出异常
throw myOutOfRangeException("年龄越界了!");
}
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
try {
Person p("孙猴子", 500);
}
catch(myOutOfRangeException& e)
{
cout << e.what() << endl;
}
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
06.标准输入流(不常用)
总结:
cin.get() //一次只能读取一个字符
cin.get(一个参数) //读一个字符
cin.get(两个参数) //可以读字符串
cin.getline() //读取换行,并且扔掉
cin.ignore(N) //N代表忽略的字符数, 没有参数时忽略一个字符
cin.peak() //偷窥 偷看一个字符,然后放回去
cin.putback() //放回 把字符放回缓冲区
代码示例:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
/*
cin.get() //一次只能读取一个字符
cin.get(一个参数) //读一个字符
cin.get(两个参数) //可以读字符串
cin.getline() //读取换行,并且扔掉
cin.ignore(N) //N代表忽略的字符数, 没有参数时忽略一个字符
cin.peak() //偷窥 偷看一个字符,然后放回去
cin.putback() //放回 把字符放回缓冲区
*/
void test01()
{
//cin.get() //一次只能读取一个字符
char c = cin.get();
cout << "c = " << c << endl;
c = cin.get();
cout << "c = " << c << endl;
}
void test02()
{
//cin.get(两个参数) //可以读字符串
char buf[1024];
cin.get(buf, 1024);
char c = cin.get();
if (c == '\n')
{
cout << "换行还在缓冲区" << endl;
}
else
{
cout << "换行不在缓冲区了" << endl;
}
cout << buf << endl;
}
//cin.get(两个参数)读取字符串时,不会把换行符拿走,遗留在缓冲区中
void test03()
{
//cin.getline();
char buf[1024];
cin.getline(buf, 1024);
//换行不在缓冲区了
//cin.getline() 把换行符读取,并且扔掉
cout << buf << endl;
}
void test04()
{
//cin.ignore() 忽略
cin.ignore(2);//没有参数代表忽略一个字符,带参数N表示忽略N个字符
char c = cin.get();
cout << "c = " << c << endl;
}
void test05()
{
//cin.peek() 偷窥
//输入as
char c = cin.peek();
cout << "c = " << c << endl;
c = cin.get();
cout << "c = " << c << endl;
}
void test06()
{
//cin.putback();
char c = cin.get();
cin.putback(c);
cout << "c = " << c << endl;
char buf[1024];
cin.getline(buf, 1024);
cout << "buf = " << buf << endl;
}
int main(void)
{
//test01();
//test02();
//test03();
//test04();
//test05();
test06();
system("pause");
return EXIT_SUCCESS;
}
07.标准输入案例
//案例1:判断用户输入的是数字还是字符串
void test07()
{
cout << "请输入一串数字或者字符串" << endl;
//偷窥
char c = cin.peek();
if (c >= '0' && c <= '9')
{
int num;
cin >> num;
cout << "宁输入的是数字:输入的数字为" << num << endl;
}
else
{
char buf[1024];
cin >> buf;
cout << "宁输入的是字符串:输入的字符串为" << buf << endl;
}
}
//案例二:让用户输入 1-10 的数字,如果输入有误 重新输入(测试有问题,未解决)
void test08()
{
int num;
cout << "请输入 1到10 的数字:" << endl;
while (true)
{
cin >> num;
if (num > 0 && num <= 10)
{
cout << "输入的数字为:" << num << endl;
break;
}
cout << "对不起,输入的数字有误,请重新输入:" << endl;
//重置标志位
cin.clear();
//清空缓冲区
cin.sync();
//cout << "标志位" << cin.fail() << endl;//标志位为0 是正常的,1 不正常
}
}
08.标准输出流(不常用)
流对象的成员函数:
int number = 99;
cout.width(20);
cout.fill('*');
cout.setf(ios::left);//设置格式,输出内容左对齐
cout.unsetf(ios::dec);//卸载十进制
cout.setf(ios::hex);//安装十六进制
cout.setf(ios::showbase);//强制输出整数基数
cout.unsetf(ios::hex);
cout.setf(ios::oct);
cout << number << endl;
09.文件的读写操作
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//文件读写头文件
#include<fstream>
//写文件
void test01()
{
//以输出的方式打开文件
//ofstream ofs("./test.txt", ios::out | ios::trunc);
//后期指定打开方式
ofstream ofs;
ofs.open("./test.txt", ios::out | ios::trunc);
//判断是否打开成功
if (!ofs.is_open())
{
cout << "打开失败!" << endl;
}
ofs << "姓名:abc" << endl;
ofs << "年龄:10" << endl;
ofs << "性别:男" << endl;
ofs.close();
}
//文件写操作
void test02()
{
ifstream ifs;
ifs.open("./test.txt", ios::in);
//判断是否打开成功
if (!ifs.is_open())
{
cout << "打开失败" << endl;
}
第一种方式
//char buf[1024];
//while (ifs >> buf)//按行读取
//{
// cout << buf << endl;
//}
第二种方式
//char buf2[1024];
//while (!ifs.eof())//eof 读到文件尾部
//{
// ifs.getline(buf2, sizeof(buf2));
// cout << buf2 << endl;
//}
//第三种方式:按单个字符读取(不推荐)
char c;
while ((c = ifs.get()) != EOF) //EOF 文件尾
{
cout << c;
}
ifs.close();
}
int main(void)
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}