类 学习总结
类是面向对象程序设计实现信息封装的基础。
类是用户定义的数据和操作这些数据的函数的封装,类的对象使用自己的方法完成对数据的操作。
类的一般形式:
class 类名
{
public:
公有数据成员和成员函数
private:
私有数据成员 //在private中成员函数一般不使用
}; 注意:要加上分号。
私有成员只能在类中可见,不能在类外或派生类中使用。如果私有成员放在第一段,则可以省略关键词private。
struct也可以用于定义类。用struct定义类时,若不特别指出,则所有成员都是共有的。
类中成员函数写法:
void setdate(int y,int m,int d)
{
Year=y;
Month=m;
Day=d;
}
类外成员函数写法:
void student::setdate(int y,int m,int d)
{
Year=y;
Month=m;
Day=d;
}
知识总结:
一:this指针
应用情况:
1/当参数与成员变量名相同时,如this->x=x,不能写成x=x。
2/避免对同一对象进行赋值操作,判断两个对象是否相同时,使用this指针。
二:构造函数
构造函数原型:类名::类名(参数表)
构造函数与类名相同。构造函数可以有任意类型的参数,但不能有返回类型。构造函数在建立类对象时自动调用。
例:
class Date
{
public:
Date();
Date(int y,int m,int d); //构造函数
private:
int Year;
int Month;
int Day;
};
Date::Date(){}
Date::Date(int y,int m,int d)
{
Year=y;
Month=m;
Day=d;
}
重载构造函数
如果Date类具有多个构造函数,创建对象时将根据参数匹配调用其中的一个。
1/参数个数相同,参数类型不同
2/参数个数不同
例:参数个数不同
class Date
{
Date();
Date(int);
Date(int,int);
Date(int,int,int);
}
void a()
{
Date d(); //调用 Date();
Date d(2000,1,1) //调用 Date(int,int,int);
}
① 复制构造函数
类名::类名(const 类名&引用名 …)
例:
class Location
{
public:
Location(){}
Location(int xx,int yy)
{
x=xx;
y=yy;
}
void copy(const Location & p);
void setx(int x){this->x=x;} //应用this指针第一种情况
Private:
Int x,y;
};
void Location::copy(const Location & p)
{
if(&p!=this) //应用this指针第二种情况
{
X=p.x;
Y=p.y; //运算符.和->用于访问对象成员
}
}
② 返回类类型的函数
Location A()
{
Location a(0,2);
return a;
}
int main()
{
Location x(1,2);
Location s(x);
s.display(); //结果(1,2),复制构造函数完成
Location w;
w=A();
w.display(); //结果(0,2),返回类类型函数完成
return 0;
}
三:析构函数
名字与构造函数相同,但前面必须加一个波浪号(~);
析构函数没有参数,也没有返回值,而且不能重载。因此在一个类中只能有一个析构函数。
当撤销对象时,编译系统会自动调用析构函数。
四:内联函数
作用:
减少频繁调用小子程序的运行的时间开销
机制:
在编译时,将内联函数的调用以相应的代码代替
声明:
inline 函数原型
例子:inline void Location::setx(){}
五:浅复制与深复制
在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制。
即:对于复杂类型的数据成员只复制了存储地址而没有复制存储内容。
而默认复制构造函数所进行的是简单数据复制,即浅复制。
相对应的深复制通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制。
而默认复制构造函数所进行的是浅复制。
浅复制举例:
Person *p1=new Person ("lihua",21,95)
Person p2(*p1);
会出现姓名未复制的情况。
深复制
深复制构造函数必须显式定义
定义:类名::类名([const]类名 &对象名);
成员变量的处理:对复杂类型的成员变量,使用new 操作符进行空间的申请,然后进行相关的复制操作。
Test (const Test& c)
{
a=c.a;
b=c.b;
}
类的其他成员:
一:常成员
二:静态成员
三:友元函数
一:常成员
1:常数据成员
使用const说明的数据成员称为常数据成员
如 const int M; //M不可被修改
构造函数就只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。
2:常对象
说明对象时用const修饰
如 类名 const 对象名[(参数表)] 或者 const 类名 对象名[(参数表)]
在定义常对象时必须进行初始化,而且不能被更新。
例:const Location t1(1,2); //t1不能被修改
3:常成员函数
类型说明符 函数名(参数表)const;
const是函数类型的一个组成部分,因此在函数的实现部分也要带关键字const。
常成员函数不能更新对象的数据,也不能调用非const修饰的成员函数(静态成员函数和构造函数除外)
二:静态成员
类成员以static声明时,称为静态成员。
例:static int s;
静态数据成员为同类对象共享。(不属于一个单独的对象,而是为类的所有对象所共享)
静态成员函数与静态成员协同操作。
对于静态数据成员,每个类只拥有一个副本(对所有对象都是可见的)。
公有静态成员,可通过下列形式进行访问
类名::静态成员的名字
对象名.静态成员的名字
对象指针->静态成员的名字
在静态成员函数内部,直接访问。
类外静态数据成员声明:类型 类名::静态数据成员=初始化值;
例子:
class nee
{
private:
static int ss;
public:
int getss()
{
return ss;
}
};
int nee::ss=3; //类外赋值
int main()
{
nee one;
int ss=one.getss();
cout<<ss<<endl;
return 0;
}
静态成员函数
static 返回类型 静态成员函数名 (参数表)
调用公有成员函数形式:
类名::静态成员函数名(实参表)
对象.静态成员函数名(实参表)
对象指针->静态成员函数名(实参表)
私有静态成员函数不能在类外部或用对象访问。
静态成员函数仅可以访问静态成员函数或静态数据成员,主要用来访问同一类中的静态数据成员。
三:友元函数
例如在类A之外的其他地方定义了一个函数B
该函数不是属于任何类的非成员函数,
也可以是其他类的成员函数。
在类A中用friend对函数B进行声明,那么这个函数就称为类A的友元函数。
且函数B可以访问类A的私有成员。
例:
class A
{
private:
public:
friend 数据类型 名称(参数);
}
数据类型 名称 (参数)
{
} //可访问类A的私有成员
类的包含 //应用情况较多
在定义一个新的类时,通过编译器把另一个类抄进来。
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式。
应用例子:用类包含计算两点之间的距离
class Point //数据类
{
public:
Point(){}
Point(int xi=0,int yi=0){x=xi;y=yi;}
Int getx(){return x;}
Int gety(){return y;}
private:
Int x;int y;
};
class Distance //操作类
{
public:
Distance (Point xp1,Point xp2)
{
p1=xp1;
p2=xp2;
dist=省略;
}
private:
Point p1,p2;
doubledist;
}
附学生成绩信息管理:
#include <bits/stdc++.h>
using namespace std;
class Student
{
private:
int number;
string name;
float average;
int score[3];
public:
Student (int id,string na,int x,int y,int z):name(na),number(id)
{
score[0]=x;
score[1]=y;
score[2]=z;
average=(score[0]+score[1]+score[2])/3;
}
Student(){score[0]=score[1]=score[2]=0;
average=0;}
void setname(string name){this->name=name;}
int getnumber(){return number;}
void setnumber(int number){this->number=number;}
void display();
};
void Student::display()
{
cout<<number<<"\t"<<name<<"\t"<<score[0]<<"\t"<<score[1]<<"\t"<<score[2]<<endl;
}
class Student_list
{
private:
Student list[100];
int n;
public:
Student_list():n(0){}
void displaying();
void add();
void search();
void deleted();
void setting();
};
void Student_list::deleted()
{
int noss;
int flag=0;
cout<<"执行删除请输入学号:";
cin>>noss;
for (int i=0;i<n;i++)
{
if (list[i].getnumber()==noss)
{
flag=1;
cout<<"您要删除的信息如下:"<<endl;
list[i].display();
for (int j=i;j<=n-2;j++)
{
list[j]=list[j+1];
}
n=n-1;
}
}
if (flag==0)
cout<<"未找到指定内容"<<endl;
}
void Student_list::search()
{
int nos;
int flag=0;
cout<<"请输入学号以便查询:";
cin>>nos;
for (int i=0;i<n;i++)
{
if (list[i].getnumber()==nos)
{
cout<<"查询到内容!"<<endl;
cout<<"学号"<<"\t"<<"\t姓名"<<"\t"<<"数学"<<"\t"<<"英语"<<"\t"<<"C++"<<endl;
list[i].display();
flag=1;
}
}
if (flag==0)
cout<<"未查询到指定内容!"<<endl;
}
void Student_list::setting()
{
int number;
cout<<"请输入学号以修改内容"<<endl;
int flag=0;
cin>>number;
int noo;
string name;
int x,y,z;
for (int i=0;i<n;i++)
{
if (list[i].getnumber()==number)
{
flag=1;
cin>>noo>>name>>x>>y>>z;
Student temp(noo,name,x,y,z);
list[i]=temp;
}
}
if (flag==0)
cout<<"未查询到要修改的内容"<<endl;
}
void Student_list::add()
{
int no;
string name;
int x,y,z;
cout<<"请依次输入学号姓名成绩,-1结束"<<endl;
while (cin>>no&&(no!=-1))
{
cin>>name>>x>>y>>z;
Student s(no,name,x,y,z);
list[n++]=s;
}
}
void Student_list::displaying()
{
cout<<"学号"<<"\t"<<"\t姓名"<<"\t"<<"数学"<<"\t"<<"英语"<<"\t"<<"C++"<<endl;
for (int i=0;i<n;i++)
{
list[i].display();
}
}
void show()
{
cout<<"-----------输入序号以执行操作----------"<<endl;
cout<<"-----------1:查看全部信息--------------"<<endl;
cout<<"-----------2:新增学生信息--------------"<<endl;
cout<<"-----------3:删除学生信息--------------"<<endl;
cout<<"-----------4:修改学生信息--------------"<<endl;
cout<<"-----------5:查询学生信息--------------"<<endl;
cout<<"-----------0:退出该系统----------------"<<endl;
}
int main()
{
int cmd=1;
Student_list xx;
while (cmd!=0)
{
show();
cin>>cmd;
if (cmd<'0'||cmd>'5')
cout<<"输入指令有误,请重新输入!"<<endl;
system("cls");
switch(cmd)
{
case 1:xx.displaying();
break;
case 2:xx.add();
break;
case 3:xx.deleted();
break;
case 4:xx.setting();
break;
case 5:xx.search();
break;
default:break;
}
}
/*
Student_list xx;
xx.add();
xx.displaying();
xx.search();
xx.deleted();
xx.displaying();
xx.setting();
xx.displaying();
*/
return 0;
}
心得总结:
1/ 类的使用主体有两种类,一种是数据类,另一种是操作类。
2/类的知识点多,但应用时用的比较少,以后应用得到的时候再多加练习。