函数
1. 函数引用:作为参数传递还有防止内存中的数字复制导致系统处理问题。可用于参数或者是函数返回值
2. 默认参数:在函数声明或者是函数定义的时候采用为函数的参数设置默认的初始值。(注意:不能同时赋初始值),当调用函数不对参数进行赋值时就会使用默认值,同时在第一个设置默认值的参数之后的参数需要都进行默认值的参数设置。
3. 函数重载:应用于函数相同名字但是参数列表不同。(一般用于有相同的作用,但是函数的参数列表不同)。编译时,编译器会根据输入的实参匹配相应的函数
4. 函数模版:作用与上面的类似,主要用于函数的返回值类型还有形参的类型不同的情况。
定义的形式
template<typenameType1,typename Type 2>
数据类型参数标识符
实例
Template<typenameT>
T add(T a,T b)
{
Return a + b;
}
面向对象的程序设计
1 类是对象的抽象,对象是类的具体事例
定义类的格式
Class 类名
{
Private:
成员数据;
成员函数
Public:
成员数据;
成员函数;
Protected:
}.
对象的定义
class 类名 对象名
类名对象名
实例:
Useing namespace std;
Class student
{
Public://公共部分
Void print()
{
Cout<<name<<” ,”<<age<<” ,”<<endl;
}
Int getage;
Private://私人部分
Char name[128];
Int age;
Char addr[128];
}
Int student:: getage()
{
Return age;
}
Void main()
{
Student stu;
Stu.print();
Stu.getage();
Return 0;
}
注:这里显示了两种类中的函数的定义方法,一种为直接在定义中进行定义,另一种为在定义中进行声明,之后再进行定义,但是在定义的时候需要在相应的函数名称之前添加类名::代表作用域。在内部定义的默认为inline函数,在外面定义的为了提高使用效率,一般也设置为inline型
类和对象的引用
在使用的过程中的别名和指针实例:
Student *p=&stu;
P->print();
P->getage();
Student & s=stu;
S.print();
S.getage();
大型程序中的类的使用结构:类的声明放在的单独的头文件中,名字与类的名字相同,内部函数的定义则在相应的cpp文件中,在使用时包含.h即可(类在定义的时候一般第一个字母用大写的C)。
构造函数和析构函数:
构造函数主要用于定义的类的对象的初始化,构造函数的名字与类的名字相同,可以有参数,但是不能有返回值,可以使用函数重载。因而,一个类的定义之中会有很多的构造函数。另外,构造函数支持默认初始值的操作,但是容易出现错误如:
CTime(int value);
CTime(int hour =0,int minute=0,intsecond=0);
定义CTime time(10)的时候编译器无法确定使用哪个。
析构函数
需要在类的名字之前加一个~,一般起清理工作,一般对象的生命周期结束的时候会自动调用。析构函数没有返回值也没有参数,因而没有重载,所以一个类只能有一个析构函数。
(先构造的对象最后进行析构)
This指针和复制构造函数
每个对象都会有一个相应的this指针,保证成员函数所处理的是相应的对象,一般编译器默认使用,其效果如下所示:
Void CTime::setsecond(int second)
{
This->m_nsecond=second;
(*this).m_nsecond=second;
}
这两个的效果是一致的
复制构造函数:
只是一种比较特殊的构造函数,主要用于已有的对象对新的对象进行定义,举例如下:
CTime::CTime(CTime& time)
{
m-nsecond=time.second;
}
CtTme time1();
CTime time2(time1);
& 在C++中的使用方法
(详细说明https://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html)
1. 引用,只是作为引用目标的一个重名来使用
如int &ra=a; 这里的ra表示的是a的一个别名,不再分配新的存储空间
ra=1与a=1的效果是相同的。
2. 在函数的形参中进行使用,可以实现数据的传递(作用类似于指针的操作),同时防止了形参对实参的赋值所导致的内存和CPU计算能力的浪费。Swap(int a,int b)
3. 函数的返回值为引用,例子:
Float &fn2(float r)
{
Temp=(r*r*3.14);
Return temp; //这里的temp需要是全局变量
}
可以使用一下两种调用:
Floatc=fn2(10.0);
Float&d=fn2(10.0);
以上两种情况都不会产生相应的返回值的副本,如果返回值为临时或是局部变量,那么返回时被释放掉,就会导致返回失效
测试用返回引用的函数值作为赋值表达式的左值。
#include <iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10;
put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20;
cout<<vals[0];
cout<<vals[9];
}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}
类的静态成员
主要分为静态的数据成员和静态的成员函数
静态的成员函数没有this指针,所以没有办法访问非静态的成员。静态的数据成员是需要进行初始化的,但在.cpp中进行初始化时是不能在初始化之前加”static”的,静态的成员函数也是同样。
Const对象和const成员
Const 类名 对象名
类名 const 对象名均可
友元
主要分为友元函数和友元类(单向,不能传递),友元只能授予,即只能在自己的类之中设置自己的友元,设置的相应的友元可以访问自己private中的数据
1.友元函数
只要在类里面进行了声明,但是声明的位置不做强制性的要求,可以使public可以是private之后,甚至是public之前,都是可以的。
2.友元类
授予的方式与友元函数类似,友元类中的成员可以使用授予类的private成员。注意:在友元类的.h文件中需要将授予这的类进行声明,如在data.h中加入class CTime 可以不用再在.h中加入#include “CTime.h”
运算符重载:
相当于给运算符一个新的函数实现形式
定义方法
CTime operator+(CTime &time1,CTime&time2)
{
}
如果需要使用私有函数,则需要使用友元的操作。+需要有两个形参
如果是在类的定义之中采用了运算符重载则需要看好形参的个数,比如+需要有一个形参
规则:
1、 只能重载C++中原有的运算符。
2、 不会影响运算符原有的作用,只是相当于原有的扩展
3、 不能改变运算符作用对象的数量(比如+作用于其左右两个数)
4、 不能进行重载的运算符:? :, * :: sizeof
5、 必须定义为成员函数的运算符:= 、[],()
6、 只能定义为类的友元的运算符:<<>>
重载双目运算符如“+ - ==”,定义时一般使用友元的方式,即在类的外部进行定义,之后在类中将重载的函数设置为友元。如:
CTime operator+(Ctime &time1,CTime &time2)
{
}
之后在类中声明
Friend CTime operator+(CTime &time1,CTime &time2)
注意:这里由于是定义在类外,所以定义时需要用两个形参,但如果是定义为类的成员函数,那么只能定义一个形参(因为成员函数能访问自己的private成员,所有有一个形参呗默认成了自己,如“+”前面的数)。
如果做为成员函数进行定义,例子如下:
Class classname
{
Public:
CTime operator+(CTime &time2);
Private:
Protected:
}
重载单目运算符比如“++”
单目运算符在类中进行定义的时候,一般在类的内部进行,这里前置的++在重载时与后置的++不同。
CTime operator++() ; //这个是前置的++
CTime operator++(int)//这个是后置的++
流插入和流提取运算符
Istream和ostream 分别为输入流类型和提取流类型,因而在进行<<和>>的运算符重载时需要对其进行应用。例子:
Ostream& operator<< (ostream& output,CTimetime)
{
Cout<<time.hour<<time.minute<<time.second;
Returnoutput; //为了使<<能够进行级联
}
面向对象编程
继承:所谓的继承就是在已经存在的类的基础之上建立一个新的类。已存在的类叫基类,父类或是超类。新建立的类称为派生类或是子类。
派生类继承了基类所有的数据成员和方法,可以增加自己的数据成员和方法。
1.派生类的声明方式:
Class classname : <access>baseclassname
{
Private:
Public:
Protected:
}
Access表示的是继承的方式
Public:表示公有继承,即基类的各个成员的访问权限不变。(其实就相当于是直接复制过来)
Private:表示私有继承,公有和保护成员在派生类中变为保护和私有的,原来私有的的则变为不可访问的。不常用。
Protected:表示保护继承
2.派生类的构造函数和析构函数
构造函数的声明方式与正常情况一致,但是在定义的时候需要先对基类进行构造。方法如下:
假定newtime是CTime的派生类
Newtime :: Newtime()
:CTime() //使用类似于const数据初始化的方式对其进行构造。可以使用有参数的构造函数,如果不写默认为默认的构造函数
{
}
析构函数:
Newtime ~Newtime() //由于每个类只有一个析构函数,因而这里不用对基类的析构函数进行调用
{
}
函数执行顺序:
基类构造函数-》派生类构造函数-》派生类析构函数-》基类析构函数
派生类对象中的成员科宇与基类的成员的名称相同,但定义派生类对象时,引用和基类相同的成员,默认为引用的子类成员。
派生类对象也是一个基类的对象:主要是可以将派生类对象的值赋值给基类的对象,积累的指针或者是引用也可以直接引用子类的对象。但是只能使用与子类中和基类相同的方法。
Hs-a关系:
即一个类是另外一个类的成员,这里把(被包含的类认为是基类)
一般在构造函数是将基类用初始化列表的方式进行初始化。
多态:
之前的函数重载属于是编译时的多态,他们大多数有返回值或是参数的不同。
另外一种多态是运行时的多态,主要存在于基类和派生类中存在函数名,返回值,形参完全相同的成员函数时,之前,当一个基类的指针指向派生类时,他所能调用的默认是基类的成员函数。但如果将次函数设定为虚函数,那么在调用时则使用派生类中的成员函数。例子:
Newtime time(0);
CTime *p=&time;
p->gethour();//这里若在基类中gethour()函数之前加了virtual将其定义为虚函数,那么这里所使用的是newtime中的gethour(),此时newtime的gethour之前的virtual可加可不加,加上便于之后看代码时理解方便。
注意:构造函数不但能定义为虚函数,析构函数则可以,并且一般都定义为虚函数
纯虚函数: 在基类中仅仅给出函数的声明,但不对其进行定义,纯虚函数需要在声明之后加个=0;没有在派生类中重新调用这种函数之前是不能调用这类函数的。
抽象类:含有纯虚函数的类称为抽象类,只能作为派生类的基类,不能定义对象,只能定义指针。定义方法如下:
Class baseclassname
{
Virtual <类型名><函数名>(参数)=0;
}
文件操作:
头文件”fstream.h”
Fstream file;//可读也可写
Ifstream infile;//可读不可写
Ofstream outfile;//可写不可读
在使用ifstreeam和ofstream时首先定义一个对象,之后将对象和文件建立关联,然后再对对象进行操作。如:
Ifstream infile;
Infile.open(“C:\\myfile.txt”);
Std::string str;
Infile>>str;
Inflie,close();
在使用fstream进行定义后,由于可写可读,因为在open的时候需要进行打开方式的定义.
Fstream file1,file2;
File1.open(“file1.txt”,ios::in)//用于输入
File2,open(“file2.txt”,ios::in)//用于输出
在open时常常会因为文件不存在或是被占用而打开失败。
一般来说file.open(“file.txt”,ios::in)进行读打开时,若没有文件则会返回bool量flase。
而在file.open(“file.txt”,ios::out)时若文件不存在则新建一个文件,若存在则删除原有的文件的内容。
常用成员函数
File.getch(ch);//取当前文件指针处的字符给ch。
File.getline(str);//读取一行的数据
以上两个函数在读取到文件的末尾时,返回值为0.以此来判断循环结束。
向文件写入一个字符 file.put(ch);
二进制文件
打开方式:
Fstream file1;
File1.open(“file1.txt”,ios::in|ios::binary);
二进制文件的关闭方法与文本一样,读取方式不同
读取:
Infile.read(char *buff,int Num);
Buff为存储数据的缓冲区,nNum为要读取的长度
Infile.read(&stuinfo,sizeof(stuinfo)); ,每次区一个结构体stuinfo大小的数据放到次结构体中
Infile.read(pbuff, 1024*sizeof(char));
写入:
Outfile.write(pbuff,nlen);
Infile.eof()//文件结束时返回一个零值,平时为非零值。