一、类与对象的定义与访问
1、定义
(1)类定义的说明语句一般形式为:
class<类名>
{
public:
公有段数据成员和成员函数;
protected:
保护段数据成员和成员函数;
private://若放在第一段可省略
私有段数据成员和成员函数;
};//分号不能省略
(2)成员函数在类外定义:
返回类型 类名::函数名(参数表);
(3)对象定义:
类名 对象名;
2、访问
运算符“.”和“->”用于访问对象成员 //一般形式为:对象.成员函数 或 指针对象->成员函数
3、this指针(在类内使用,指明对象本身)
例如:void setname (string name){this->name=name;}
二、构造函数和析构函数
1、构造函数
系统自动初始构造函数原型:类名::类名(){};
定义带参构造函数:类名::类名(形参表)
{ 给数据成员赋初值操作等; }
class date
{
int year,month,day;
public:
date(int,int,int);
void setdate(int y,int m,int d);
void printdate();
};
date::date(int y,int m,int d)
{
year=y;month=m;day=d;
}
带默认值的构造函数:box(int h=10,int w=10,int l=10);//定义了全部带默认值的构造函数,不能再定义无参构造函数
class box
{
int height,width,length;
public:
box();//不能定义
box(int h=10,int w=10,int l=10);
int volume();
};
box::box(int h,int w,int l):height(h),width(w),length(l){}
int box::volume()
{
return height*length*width;
}
int main()
{
box box1;
box1.volume();//结果输出10,10,10
box box2(12,30,25);
box2.volume();//结果输出12,30,25
box box3(30,25);
box3.volume();//结果输出30,25,10
return 0;
}
注:(1)当定义带参构造函数后,初始构造函数不再存在,需重新定义。
(2)使用构造函数的初始化列表进行初始化:
形式:成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
必须使用参数初始化列表对数据成员进行初始化的几种情况:
1、数据成员为常量
2、数据成员为引用类型
3、数据成员为没有无参构造函数的类的对象
(3)类成员的初始化顺序:按照数据成员在类中的声明顺序进行初始化,与初始化成员列表中出现的顺序无关
2、重载构造函数
如果类内有多个构造函数,创建对象时,将根据参数匹配调用其中的一个。
class date
{
public:
date();
date(int);
date(int,int);
date(int,int,int);
//...
};
//...
void f()
{
date d;
date d1(2000);
date d2(2000,1);
date d3(2000,1,1);
}
3、复制构造函数
用一个已有的同类型对象的数据对新对象进行初始化。
类名::类名(const 类名&引用名,…);//为了保证所引用对象不被修改,通常把引用参数说明为const参数
如果没有显式定义复制构造函数,系统自动生成一个默认形式的复制构造函数。
class box
{
int length,height,width;
public:
box(int=10,int=10,int=10);
box(const box &b)//此处复制构造函数定义该对象变为实参对象各项数据的二倍
{
height=2*b.height;width=2*b.width;length=2*b.length;
}
int volume();
};
box::box(int h,int w,int l):length(l),width(w),height(h){}
int box::volume(){return width*length*height;}
int main()
{
box box1(1,2,3),box2(box1),box3=box2;
cout<<box1.volume()<<endl;
cout<<box2.volume()<<endl;
cout<<box3.volume()<<endl;
}
关于浅复制与深复制:
(1)浅复制:在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制。
即:对于复杂类型的数据成员只复制了储存地址而没有复制储存内容。
默认复制构造函数所进行的是简单数据复制,即浅复制。
(2)深复制:不仅复制了数据成员,也复制了资源的复制方式称为深复制。//可通过new操作符进行空间申请,然后进行相关的复制操作
4、析构函数
对象生存期结束时,需要做清理工作,比如:释放成员(指针)所占有的储存空间
析构函数自动调用(隐式调用)
析构函数没有返回值,不能有参数,也不能重载
默认:类名::~类名(){}
三、类的其他成员
1、常成员(只读不写)(通过const约束)
(1)常数据成员:指数据成员在实例化被初始化后,其值不能改变。
由构造函数通过初始化列表对该常数据成员进行初始化。
(2)常对象:在定义常对象时必须进行初始化,而且不能被更新。
说明:不能更改对象的数据成员,常对象只能调用它的常成员函数、静态成员函数、构造函数(具有公有访问权限)
(3)常成员函数
格式如下:类型说明符 函数名(参数表) const;//调用时也要加const
说明:不能更新对象数据,也不能调用非const修饰的成员函数(静态成员函数、构造函数除外)
2、静态成员(以static声明)
(1)静态数据成员:同类对象共享,直接赋值初始化。//要求类中声明,类外定义
类型 类名::静态数据成员=初始化值;
(2)静态成员函数:处理静态数据成员
3、友元
(1)友元函数
如果在类A以外的其他地方定义了一个函数,这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数,在类A中用friend对其进行声明,此函数就称为本类的友元函数。友元函数可以访问该类中的私有成员。
class A
{
private:
int i;
void memberfun(int);
friend void friendfun(A *,int);//friendfun是类A的友元
};
...
void friendfun(A *ptr,int x)
{
ptr->i=x;
}
void A::memberfun(int x)
{
i=x;
}
(2)友元类
若F类是A类的友元类,则F类的所有成员函数都是A类的友元函数。
class A
{
friend class B;//类B通常为对类A的数据操作或类之间传递消息的辅助类
public:
...
private:
...
};
class B
{
public:
...
private:
...
};
四、类的包含
类的数据成员为另一个已经定义的类对象。
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化列表。
构造函数(形参表):对象成员1(形参表),…,对象成员n(形参表);
成员对象的构造函数调用次序和成员对象在类中的说明次序一致。
class A
{
public:
A(int x):a(x){}
int a;
};
class B
{
public:
B(int x,int y):aa(x){b=y;}//用初始化列表对成员对象进行初始化
void out(){cout<<"aa="<<aa.a<<endl<<"b="<<b<<endl;}
private:
int b;
A aa;//数据成员为其他类的对象
};
int main()
{
B objB(3,5);
objB.out();
}
对象数组:指每一数组元素都是对象的数组。
定义格式如下:类名 数组名[下标表达式];
利用对象数组解决问题,如简单的成绩管理系统:
#include<bits/stdc++.h>
using namespace std;
class student//先定义一个学生类,为后面的操作类提供一个基础单元
{
string name;
int no;
int score[3];
float average;
int order;
public:
student()
{
score[0]=score[1]=score[2]=average=0;
order=1;
}
student(int id,string na,int x,int y,int z):name(na),no(id)
{
score[0]=x;score[1]=y;score[2]=z;
order=1;average=(score[0]+score[1]+score[2])/3;
}
int getno(){return no;}
float getaverage(){return average;}
void setaverage(float ave){average=ave;}
void setorder(int x){order=x;}
int getorder(){return order;}
string getname(){return name;}
void setname(string name){this->name=name;}
void display();
};
void student::display()
{
cout<<name<<"\t"<<no<<"\t"<<score[0]<<"\t"<<score[1]<<"\t"<<score[2]<<"\t"<<average<<"\t"<<order<<endl;
}
class student_operate//操作类,用于管理学生类信息的增、删、查、改等
{
student list[60];//操作对象有多个,故操作类数据成员为一个对象数组
int n;
public://下面是该操作类的主要功能
student_operate():n(0){};
void add();
void deletestu();
void query();
void change();
void display(int flag);
int search(int no);
void sortlist();
};