day9-C++学习

1. 类型转换

静态类型转换-static_cast
使用方式:static_cast< 目标类型>(原始数据)

基础类型转换

void test()
{
	char a = 'a';

	double d = static_cast<double>(a);//隐式类型转换,将字符型转换为double类型

	cout << "d =" << d << endl;//97
}

基类与派生类之间的转换

class Base{};//基类
class Child :public Base{};//派生类
class Other{};//其它类
void test2()
{
	Base* base = NULL;
	Child* child = NULL;

	//把base转为Child*类型,向下转换,不安全
	Child* child2 = static_cast<Child*>(base);

	//把child转为Base*类型,向上转换,安全
	Base* base2 = static_cast<Base*>(child);

	//转other类型
	//Other* other = static_cast<Other*>(base);类型转换无效

}

/*
  子类转换成父类:安全。
  父类转换成子类:不安全。
*/

动态类型转换-dynamic_cast
使用方式:dynamic_cast< 目标类型>(原始数据)

基础类型不可以转换

void test3()
{
	//基础类型不可以转换
	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 test4()
{
	Base2* base = NULL;
	Child2* child = NULL;

	//child转Base2*,向上转,安全
	Base2* base2 = dynamic_cast<Base2*>(child);

	//base转Child2*,向下转,不安全
	//Child2* child2 = dynamic_cast<Child2*>(base);

	//dynamic_cast如果发生了多态,那么可以让基类转为派生类,向下转换
	Base2* base3 = new Child2;
	Child2* child3 = dynamic_cast<Child2*>(base3);
}
/*
  子类转换成父类:可以。
  父类转换成子类:不可以。
*/
//在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全

常量转换-const_cast
使用方式:const_cast< 目标类型>(原始数据)

void test5()
{
	const int* p = NULL;
	//去除const
	int* newp = const_cast<int*>(p);

	int* p2 = NULL;
	const int* newp2 = const_cast<const int*>(p2);

	//不能对非指针或非引用的变量进行转换
	//const int a = 10;
	//int b = const_cast<int>(a);
	//引用
	int num = 10;
	int& numRef = num;

	const int& numRef2 = const_cast<const int&>(numRef);
}

重新解释转换-最不安全,不推荐

void test6()
{
	int a = 10;
	int* p = reinterpret_cast<int*>(a);


	Base* base = NULL;
	Other* other = reinterpret_cast<Other*>(base);
}

2.异常的基本处理

int myDevide(int a, int b)
{
	if (b == 0)
	{
		//如果b是异常,就抛出异常
		//return -1;
		
		throw - 1;//抛出int类型异常
		throw 3.14;//抛出double类型异常
		throw 'a';//抛出char类型异常,异常必须处理,否则会崩掉
	}
	return a / b;
}


void test1()
{
	int a = 10;
	int b = 0;
	//int ret = myDevide(a, b);//早期如果返回-1,无法区分到底是结果还是异常
	//C++中异常处理
	try//试图执行 try{}中的内容
	{
		myDevide(a, b);
	}
	catch (int)//捕获异常
	{
		cout << "int类型异常捕获" << endl;
	}
	catch (double)//捕获异常
	{
		//如果不想处理这个异常,可以继续向上抛出
		throw;
		cout << "double类型异常捕获" << endl;
	}
	catch (...)//捕获异常
	{
		cout << "其他类型异常捕获" << endl;
	}
}

int main()
{
	try
	{
		test1();
	}
	catch (double)//如果异常都没有处理,那么成员terminate函数使程序中断
	{
		cout << "main函数中double类型异常捕获" << endl;
	}
	catch (...)//捕获异常
	{
		cout << "main函数中其他类型异常捕获" << endl;
	}
	system("pause");
	return 0;
}

自定义异常类

class myExceotion //自定义异常类
{
public:
	void printError()
	{
		cout << "自定义的异常" << endl;
	}
};

class Person
{
public:
	Person()
	{
		cout << "Person构造" << endl;
	}
	~Person()
	{
		cout << "Person析构" << endl;
	}
};

int myDevide(int a, int b)
{
	if (b == 0)
	{
		//栈解旋
		//从try开始到throw抛出异常之前,所以栈上的对象都会被释放
		//栈上构造和析构顺序相反
		Person p1;
		Person p2;

		throw myExceotion();//匿名对象
	}
	return a / b;
}


void test1()
{
	int a = 10;
	int b = 0;
	try
	{
		myDevide(a, b);
	}
	catch (myExceotion e)
	{
		e.printError();
	}
	catch (...)//捕获异常
	{
		cout << "其他类型异常捕获" << endl;
	}
}

异常的接口说明
如果想抛出特定的类型异常 ,可以利用异常的接口声明
void func() throw (int) 只能抛出 int类型
void func() throw() 不抛出任何类型异常

异常变量的生命周期

class myException
{
public:
	myException()
	{
		cout << "myException的默认构造" << endl;
	}
	myException(const myException& e)
	{
		cout << "myException的拷贝构造" << endl;
	}
	~myException()
	{
		cout << "myException的析构调用" << endl;
	}
};

void dowork()
{
	throw new myException();
}

void test1()
{
	try
	{
		dowork();
	}
	catch (myException *e)//myException e,会多开销一份数据,会调用拷贝构造,然后调用析构
	//推荐使用MyException &e,就一份数据
	{
		cout << "捕获异常" << endl;

		delete e;//自觉释放
	}
}

异常的多态使用
利用多态来实现 printError同一个接口调用
抛出不同的错误对象,提示不同错误

//异常基类
class BaseException
{
public:
	virtual void printError()
	{
	}
};

class NULLPointer :public BaseException
{
public:
	virtual void printError()
	{
		cout << "空指针异常" << endl;
	}
};

class OutofRange :public BaseException
{
public:
	virtual void printError()
	{
		cout << "越界异常" << endl;
	}
};

void dowork()
{
	throw NULLPointer();
	throw OutofRange();
}

void test1()
{
	try
	{
		dowork();
	}
	catch (BaseException &e)
	{
		e.printError();
	}
}

使用系统标准异常

//系统提供标准异常,要包含头文件
#include<stdexcept>


class Person
{
public:
	Person(string name,int age)
	{
		this->m_name = name;
		if (age < 0 || age>200)
		{
			throw out_of_range("年龄越界");
		}
	}

	string m_name;
	int m_age;
};

void test1()
{
	try
	{
		Person p("李四", 300);
	}
	catch (out_of_range &e)
	{
		cout << e.what() << endl;
	}
}

编写自己的异常类

class myOutOgRangException :public exception
//自己的异常类需要继承于系统提供的异常基类exception
{
public:
	myOutOgRangException(string errorInfo)
	{
		this->m_ErrorInfo = errorInfo;
	}
	virtual ~myOutOgRangException()
	{
	}
	virtual const char* what() const
	{
		//构造时候传入错误信息字符串,what返回这个字符串
		//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 myOutOgRangException(string("年龄越界"));
		}
	}
	string m_name;
	int m_age;
};

void test1()
{
	try
	{
		Person p("李四", 300);
	}
	catch (myOutOgRangException &e)
	{
		cout << e.what() << endl;
	}
}

3.标准输入/输出流

cin.get 缓冲区中读取一个字符

void test()
{
	//输入as
	char c = cin.get();
	cout << "c = " << c << endl;//a
	
	c = cin.get();
	cout << "c = " << c << endl;//s

	c = cin.get();
	cout << "c = " << c << endl;//换行

	c = cin.get();
	cout << "c = " << c << endl;//等待下一次输入
}

cin.get(两个参数) 不读换行符

void test1()
{
	char buf[1024];
	cin.get(buf, 1024);
	char c = cin.get();
	if (c == '\n')
	{
		cout << "换行还在缓冲区" << endl;
	}
	else
	{
		cout << "换行不在缓冲区" << endl;
	}
	cout << buf << endl;
}//cin.get(两个参数)读取字符串时,不会拿走换行符

cin.getline () 读取换行 并且扔掉

void test2()
{
	char buf[1024];
	cin.getline(buf, 1024);
	char c = cin.get();
	if (c == '\n')
	{
		cout << "换行还在缓冲区" << endl;
	}
	else
	{
		cout << "换行不在缓冲区" << endl;
	}
	cout << buf << endl;
}

cin.ignore 忽略 (N) N代表忽略字符数

void test3()
{
	//输入ass,输出s
	cin.ignore(2);//没有参数代表忽略一个字符,带参数N,忽略N个字符

	char c = cin.get();

	cout << "c=" << c << endl;
}

cin.peek 偷窥 偷看1个字符然后放回去

void test4()
{
	//输入as
	char c = cin.peek();//偷看a,再放回缓冲区

	cout << "c=" << c << endl;//a

	c = cin.get();

	cout << "c=" << c << endl;//a
}

cin.putback 放回 把字符放回缓冲区

void test5()
{
	char c = cin.get();
	cin.putback(c);
	
	char buf[1024];

	cin.getline(buf, 1024);
	cout << buf << endl;
}

案例1 判断输入的是字符串还是数字

void test6()
{
	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;
	}
}

案例2 输入1到10的数字,如果输入有误,重新输入

void test7()
{
	int num;
	while (true)
	{
		cin >> num;
		if (num > 0 && num <= 10)
		{
			cout << "数字为:" << num << endl;
			break;
		}
		//cout << "重新输入" << endl;

		
		//重置标志位
		cin.clear();
		cin.ignore(numeric_limits<std::streamsize>::max(),'\n');//清空缓冲区
		//vs新版本不支持cin.syne()清空缓冲区
		cout << "标志位:" << cin.fail() << endl;//标志位0是正常的,1是不正常的
	}
}

cout.put()和cout.write()

void test1()
{
	cout.put('a').put('b');

	char buf[1024] = "hello";
	cout.write(buf,strlen(buf));
}

流对象的成员函数

void test2() 
{
	int number = 99;
	cout.width(20);//宽度格式设置20
	cout.fill('*');//填充*
	cout.setf(ios::left);//设置格式,输出内容左对齐
	cout.unsetf(ios::dec); //卸载十进制
	cout.setf(ios::hex);//安装十六进制
	cout.setf(ios::showbase);//强制输出整数基数,0/0x
	cout.unsetf(ios::hex);//卸载十六进制
	cout.setf(ios::oct);//安装八进制
	cout << number << endl;
}

使用控制符

#include <iomanip>//使用控制符的头文件
void test3() 
{
	int number = 99;
	cout << setw(20)//宽度格式设置20
		<< setfill('~')//填充~
		<< setiosflags(ios::showbase)//强制输出整数基数
		<< setiosflags(ios::left)//设置格式,输出内容左对齐
		<< hex
		<< number
		<< endl;
}

4.文件操作

#include <fstream>//文件读写头文件

//写文件
void test1()
{
	//以输出的方式打开文件
	//ofstream ofs("./test.txt", ios::out | ios::trunc);
	//后期指定打开方式
	ofstream ofs;
	ofs.open("./test.txt", ios::out | ios::trunc);
	if (ofs.is_open())
	{
		cout << "打开成功" << endl;
	}
	else
	{
		cout << "打开失败" << endl;
	}
	ofs << "姓名:李四" << endl;
	ofs << "年龄:94" << endl;
	ofs << "性别:男" << endl;
}
//读文件
void test2()
{
	ifstream ifs;
	ifs.open("./test.txt", ios::in);
	if (ifs.is_open())
	{
		cout << "打开成功" << endl;
	}
	else
	{
		cout << "打开失败" << endl;
	}
	//第一种读的方式
	//char buf[1024];
	//while (ifs >> buf)//按行读
	//{
	//	cout << buf << endl;
	//}

	//第二种读的方式
	//char buf[1024];
	//while (!ifs.eof())//eof读到文件尾部
	//{
	//	ifs.getline(buf, sizeof(buf));
	//	cout << buf << endl;
	//}

	//第三种读的方式
	//char c;
	//while ((c = ifs.get()) != EOF)//按照单个字符读取,EOF文件尾
	//{
		//cout << c;
	//}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值