我们都忽略了C++IO流,异常,模板的一些常用方法

文件操作

C++的文件操作和C语言的大体上还是一样的,C++是用的对象,C语言是直接用的函数,操作是和C语言学的一样
C++的文件操作是用得 fstream 类型对象来操作,需要打开头文件fstream
fstream文件流 ifstream输入文件流 ofstream输出文件流
在这里插入图片描述文件对象,就是通过这个对象来实现文件的操作

fstream file;

如果需要用多个打开方式就多项两个中间用 | 隔开

 file.open("文件路径",打开方式|打开方式|打开方式~~~);

关闭,打开了就要记得关闭

 file.close();

1,打开方式
ios::in 读取,如果文件不存在就打开失败
ios::out 写入 如果文件不存在就生成文件,文件存在清空里面的内容
ios::app 追加 如果文件不存在就生成文件,文件存在就在后面追加内容
ios::binary 二进制文件,
2,判断文件是否打开成功

if(file.is_open())//如果返回是1就是成功,是0就失败
cout<<"成功"<<endl;
else
cout<<"失败"<<endl;

3,读写单个字符
char s=‘s’;
写入一个字符

 file.put(s);

读取一个字符

 file.get(s);

读取一个字符

 s=file.get();

4,读写多个字符
char ss[128];
最多可以读取128个字符 遇到换行会结束读取

 file.get(ss,128);

最多读取128个字符 遇到空格或者换行会结束

 file.get(str,128,' ');

从键盘输入,遇到空格停止,赋值给ss

 cin.get(ss,128,' ');

读取一行,遇到换行结束,赋值给ss

 file.getline(ss,128);

最多读取128个字符 遇到空格或者换行会结束,赋值给ss

 file.getline(ss,128,' ');

5,文件末尾

file.eof() //返回1,读到了文件末尾

ios::beg;文件开头
ios::cur;文件当前位置
ios::end;文件结尾,
6,从当前位置完后面移动

file.seekp(5,ios::cur);

7,用文本的方式存储信息时,使用二进制的方式。读写二进制文件不能使用类似cin、cout从流中读写数据的方法,我们可以调用ifstream类和fstream类的read成员函数从文件中读取数据,调用ofstream和fstream的write成员函数向文件中写入数据。

异常

异常不等于错误 任何东西都可以当作异常
1,抛出异常

int Return(int a, int b)
{
	if (b == 0)
	{
		throw 1;
	}
	return a / b;
}

抛出异常未作处理,系统调用abort终止程序
2,捕获异常与处理异常

try
{
	Return(1,2);
}
catch (int) //throw  xx   和catch 括号类型要一致
{
	cout << "除数不能为零" << endl;
}

3,try和catch的匹配

#include <iostream>
using namespace std;
int main()
{
	int m = 1;
	cin >> m;
	try
	{
		cout << endl;
		//除非系统帮你写好的异常
	}
	catch (int)
	{
		cout << "int 异常差生" << endl;
	}
	catch (double)
	{
		cout << "double异常差生" << endl;
	}
	catch (char)
	{
		cout << "char异常差生" << endl;
	}
	system("pause");
	return 0;
}

4,类异常
系统有一个异常类 exception

#include <iostream>
#include <string>
using namespace std;
class base :public exception
{
	string error;
public:
	base(string error)
	{
		this->error = error;
	}
	virtual const char* what()const
	{
		return this->error.c_str();//返回的是一个指向字符串的常量指针
	}
};
class Person
{
	string name;
	int age;
public:
	Person(string name, int age)
	{
		this->name = name;
		if (age < 0 || age>200)
		{
			throw base("年龄输入不合理");
		}
	}
};
void text()
{
	try
	{
		Person person("aa", 300);
	}
	catch (base &b)
	{
		cout << b.what();
	}

}
int main()
{
	text();
	system("pause");
	return 0;
}

模板

模板是泛型编程的一个基础,模板就像练字本一样,你用钢笔,铅笔,圆珠笔都只需要照着练字本上面的那个字写,就可以写出来一个很漂亮的字。模板就如通这个一样

函数模板的基本用法

template<typename T> 模板头,固定写法,下面紧跟一个类(类模板)或者函数(函数模板)
里面的任意类型可多写,template<typename T1,typename T2>,这样就是两个任意类型,T1,T2的命名要符合命名规则,typename可以以换成class,这里的效果是一样的
T:这里的是表示的一个任意类型,是一个类型

template<typename T>

void fun(T& a,T &b)

{cout<<a<<endl<<b<<endl;}

这里的fun函数的参数是一个任意类型的a和b

int a=1,b=2;char c='x';

fun(a,b); 隐式推导类型,需要有参数的类型才可以推导,相当于T是int类型
fun(a,c); 推导不出来T,因为的这里ac是不同的类型,而任意类型只有一个T,T不能即是int又是char
fun(a,b); 显示指定类型,就是说我知道这个任意类型是什么类型,直接告诉了编译器

函数模板与普通函数的区别

1、函数模板和普通函数可以重载
2、如果出现重载,优先调用普通函数,如果普通函数没有实现,报错
3、想要强制掉用模板,那么可以使用显示制定类型调用
4、如果函数模板可以产生更好的匹配,那么优先调用函数模板

模板的局限性及解决

template<class T>
bool myCompare(T &a, T &b)
{
 if (a == b)
 {
  return true;
 }
 return false;
}

比如这个函数,如果说传的是个对象,那么不是能直接进行比较的,可以重载运算符==来进行一个比较,也可以使用语法:template<> 返回值 函数名<具体类型>(参数) {}

template<> bool myCompare<Person>(Person &a, Person &b)
{
  if (a.m_Age == b.m_Age)
 {
  return true;
 }
 return false;
}

类模板的基本使用

Person p(“hello”,666);类模板不支持自动推到类型
Person<string,int>(“hello”,666);必须使用显示指定类型

类模板做函数的参数

类模板可以有默认类型

template <class NT, class AT = int>
class Person
{
public:
 Person(NT name, AT age)
 {
  this->m_Name = name;
  this->m_Age = age;
 }
 void showPerson()
 {
  cout << "姓名:" << this->m_Name << " 年龄: " << this->m_Age << endl;
 }
 NT m_Name;
 AT m_Age;
};

类模板和继承

template <class T>
class Base
{
public:
 T m_A; //double类型
};

child继承与 base,必须告诉base中的T的类型,否则T无法分配内存
在继承时候,子类继承的时候要知道父类的类型

class Child :public Base<int>
{
};
//child2 也是模板类
template<class T1, class T2>//两个任意类型,一个给父类用,一个自己用
class Child2 :public Base<T2>
{
public:
 Child2()
 {
  cout << typeid(T1).name() << endl;
  cout << typeid(T2).name() << endl;
 }
public:
 T1 m_B; //int类型
};
void test01()
{
 Child2<int, double>child;//由用户指定类型

}

类模板类外实现成员函数

模板头
返回值类型 类名<参数>::成员函数(参数)
{}

template <class T1, class T2>//模板头要写上
Person<T1, T2>::Person(T1 name, T2 age){}

template <class T1, class T2>
void Person<T1, T2>::showPerson(){}

类模板的分文件编写

1、类模板中成员函数的创建是在调用阶段,导致分文件编写时链接不到,所以会报错
在这里插入图片描述
解决方法,直接将声明和实现写到同一个头文件中,把后缀名改为.hpp,hpp是约定俗成

类模板碰到了友元函数,类内实现

友元函数类内实现

template<class T1, class T2>
class Person
{
 friend void printPerson(Person<T1, T2> & p)
 {
  cout << "姓名:" << p.m_Name << "  年龄: " << p.m_Age << endl;
 }
public:
 Person(T1 name, T2 age)
 {
  this->m_Name = name;
  this->m_Age = age;
 }
private:
 T1 m_Name;
 T2 m_Age;
};
void test()
{
 Person<string, int> p("hello", 66);
 printPerson(p);
}

猜你喜欢

转载自blog.csdn.net/qq_45893999/article/details/106547670