类简单来说是用户自己定义的数据类型。对象是用类这个数据类型定义的一个变量。
类的基本思想是数据抽象和封装。
数据抽象:
依赖接口和实现分离编程的技术。
- 接口:用户可以执行的操作。
- 实现:包括类的数据成员、各种函数。
抽象数据类型包括数据以及操作两部分,即成员函数以及数据成员。
类的定义:
class
{
private:
int a;
double b;
string c;
public:
void input()
{
cin>>a>>b>>c;
}
};
private:一般是私有数据成员,私有函数较为少见。私有数据成员只能由私有函数或者友元函数访问,确保了函数的封装性。
成员函数在声明时,可以在结构体(类class内)声明,但是有时候函数太长,声明在类里面太难看,就只能声明在类之外,这时候就不能只写成普通函数的样子了,因为这样会被定义成一个普通函数,就不能使用私有成员了。
要想将数据成员定义在类外,可以用:类名::成员函数()的形式。
- C++引入了class来定义类,与struct类似,不同之处在于struct默认public,而class默认private。
封装
将数据和操作绑在一起,加上访问控制,称作封装。外部主要通过接口访问 对象中的数据,称作向对象发送信息。
访问限定符
private、public、porotected限定符。前两个比较容易理解,写代码也比较常用,最后一种现在还不常使用,主要用于继承中(暂时还没学)。
this指针
每个成员函数都有的隐藏参数:地址。指向接收消息的对象,成为this指针。
他是一个常量,含有实施调用的对象的地址。既不能改变他的值,也不能取他的地址。
this指针常用于:
- 区分与变量名重名的数据成员
- 返回当前对象
- 获取当前对象的地址
使用样例:
class X {
int m;
public:
void setVal(int m) { this -> m = m; }
X add(const X& a) {
m += a.m;
return *this; //返回当前对象
}
void copy(const X& a) { //复制对象
if (this == &a) //同一对象,无需复制
return;
m = a.m; //拷贝复制
}
};
访问器和修改器
进行访问修改私有成员的函数称为访问器和修改器,一般将名称设为:setxxx、getxxx。
友元
使用时在函数前面加上friend就可以。在类外就可以使用私有函数了。
但是为了封装性,一般不用友元,我们一般只有在重铸运算符的时候使用友元。
构造函数和构析函数
构造函数对对象进行初始化工作,构析函数是对对象进行销毁。
构造函数和构析函数都是以类名为名称,没有返回值。构析函数前面加个波浪号。
构造函数必须写两个,一个是有参的构造函数,一个是无参的构造函数。因为我们在定义函数时,会将其设置为普通的数据模式,这就会调用无参的构造函数。
构析函数会将对象的生命周期结束,并且函数自动调用。可有可无。
const成员
在数据成员声明前加const可以将其限定为常量,在构造函数的初始化列表中进行初始化。
将一个成员函数声明为const,表明这个成员函数不会修改对象的数据成员。跟普通的const函数定义的不同性在于,他的const并不放在最前面:
返回类型 成员函数名(参数表) const {函数体};
声明:
返回类型 成员函数名(参数表)const;
常函数与常对象有着复杂的关系。
常对象只能被常函数调用,不能被非常函数调用(防止非常函数改变常对象的值)
常函数可以调用非常对象,也可以调用常对象。
static成员
static数据成员属于整个类,不属于某个对象。所以只是在类作用域中起作用,不会与全局域中的名字冲突。并且这个类的所有对象共同访问,虽然如此,看起来特别的公有化,但是依然可以实现信息隐藏。
典型的使用样例是对象计数器,用来统计有多少个对象。使用时可以在构造函数时count++,在析构函数里面count--。
static数据成员的定义:
static int obj;
数据成员不属于某个特定的对象,因而不能在构造函数中初始化,必须在类外一定义完类就初始化。
static const int a=2;静态常量数据成员则必须在类中进行初始化。
访问:
(1)成员访问运算符"."、"->"。
(2)类名限定的静态成员名:类名::count;
static成员函数:
static int getcount(){ };
静态成员函数只能访问static类型数据成员。
老师改的同学的类的超级利用:
#include <iostream>
#include <vector>
#include <string>
#include<algorithm>
using namespace std;
struct Cj{
string nam;
double grade;
double jd;
}ob;
class Student{
string name;
string xuehao;
string zy;
vector<Cj> st;
double JD;
int pm;
public:
Student():name(""),xuehao("") {st.clear();}
Student(string na,string xh,string zyxx):name(na),zy(zyxx),xuehao(xh)
{
st.clear();
input();
jisuan();
}
void input();
friend bool cmp(Student d1,Student d2);
void jisuan();
void print ();
string getname(){
return name;
}
string gatxuehao(){
return xuehao;
}
string getzy(){
return zy;
}
int getpm(){
return pm;
}
void setPm(int no){pm=no;}
};
void Student::input(){
cout<<"现在输入"<<name<<"同学的成绩信息:"<<endl;
cout<<"输入成绩(名称 成绩 学分)end 结束输入"<<endl;
while(true){
cin>>ob.nam;
if(ob.nam=="end"||ob.nam=="End"||ob.nam=="END") break;
cin>>ob.grade>>ob.jd;
st.push_back(ob);
}
}
void Student::jisuan(){
double sum=0,sum1=0,sum2=0;
vector<Cj>::iterator i;
for( i=st.begin();i!=st.end();i++){
sum=sum+i->jd;
if(i->grade>=60)
sum1=sum1+(i->grade/10-5)*i->jd;
}
JD=sum1/sum;
}
void Student::print (){
cout<<"绩点"<<JD<<' '<<"姓名:"<<name<<' '<<"学号"<<xuehao<<' '<<"专业班级:"<<zy<<' ';
vector<Cj>::iterator i;
for( i=st.begin();i!=st.end();i++){
cout<<i->nam<<' '<<i->grade<<' ';
}
cout<<pm<<endl;
}
bool cmp(Student d1,Student d2)
{
return d1.JD>d2.JD;
}
int main()
{
string name,xuehao,zy;
int n;
Student ob[40];
cout<<"请输入学生姓名:";
cin>>name;
cout<<"请输入学生学号:";
cin>>xuehao;
cout<<"请输入专业班级(如18计算机3班):";
cin>>zy;
Student st(name,xuehao,zy);
st.setPm(1);
st.print();
cout<<"请输入班级人数:";
cin>>n;
for(int i=0;i<n;i++){
cout<<"请输入学生姓名:";
cin>>name;
cout<<"请输入学生学号:";
cin>>xuehao;
cout<<"请输入专业班级(如18计算机3班):";
cin>>zy;
Student st(name,xuehao,zy);
ob[i]=st;
}
sort(ob,ob+n,cmp);
for(int i=0;i<n;i++) ob[i].print();
return 0;
}