目录
一、对象指针
定义:占用一块连续的内存区域,由此可以使用一个指向对象的指针来访问对象。它指向存放该对象的地址。
优点:
(1)实现地址传递
(2)使用对象指针效率高
//Clock.h
#include<iostream>
using namespace std;
class Clock
{
public:
Clock(int h = 0,int m = 0,int s = 0)
{
H = h;
M = m;
S = s;
cout << "Clock()" << endl;
}
~Clock()
{
cout << "~Clock()" << endl;
}
void SetTime(int h,int m,int s)
{
H = h;
M = m;
S = s;
}
void ShowTime()
{
cout << H << ":" << M << ":" << S <<endl;
}
Clock(Clock &p)
{
H = p.H;
M = p.M;
S = p.S;
}
void AddTime(Clock *Cp)
{
H = (Cp -> H + H + (Cp -> M + M + (Cp -> S + S ) / 60 ) / 60 ) % 24;
M = (Cp -> M + M + (Cp -> S + S) / 60 ) % 60;
S = (Cp ->S + S ) % 60;
}
void AddTime(int h,int m,int s)
{
H = (h+ H + (m + M + ( s + S) / 60 ) / 60) % 24;
M = (m + M + (s + S) / 60) % 60;
S = (s + S) % 60;
}
void AddTime(int s)
{
H = (H + (M + ( s + S) / 60 ) / 60) % 24;
M = (M + (s + S) / 60) % 60;
S = (s + S) % 60;
}
private:
int H;
int M;
int S;
};
//main.cpp
#include<iostream>
#include"Clock.h"
using namespace std;
int main()
{
Clock C1;
Clock C2(8,20,20);
C1.AddTime(4000);
C1.ShowTime();
C2.AddTime(&C1);
C2.ShowTime();
return 0;
}
二、对象引用
对象引用就是对某类对象定义一个引用,其实只是通过将被引用对象的地址赋给引用对象,使二者指向同一块内存空间,引用对象是被引用对象的别名。
PS:
(1)对象引用与被引用对象必须是同类型的。
(2)除非是作为函数参数与函数返回值,对象引用在定义时必须要初始化。
(3)定义一个对象引用并没有定义一个对象,所以不分配地址空间,不调用构造函数。
(4)对象引用通常作为函数的参数,它具有指针的优点,还比指针更简洁。
void AddTime(Clock &Cr)
{
H = (Cr.H + H + (Cr.M + M + (Cr.S + S ) / 60 ) / 60 ) % 24;
M = (Cr.M + M + (Cr.S + S) / 60 ) % 60;
S = (Cr.S + S ) % 60;
}
将main.cpp中C2.AddTime(&C1);替换成 C2.AddTime(C1);.
运行结果和上图相同。
三、对象数组
概念:对象数组是以对象为元素的数组。对象数组的定义、赋值、引用和普通数组相同。
//Score.h
#include<iostream>
using namespace std;
const double Rate = 0.7; //平时成绩比例
class Score
{
public:
Score(long = 0,char * = NULL,int = 0,int = 0, int = 0);//构造函数
void Count(); //计算总评成绩
void ShowScore(); //显示成绩
private:
long Sno; //学号
char *Sname; //姓名
int Speace; //平时成绩
int Sfinale; //期末考试成绩
int Stotal; //总评成绩
};
//构造函数
Score :: Score(long no,char * name,int peace,int finale, int total)
{
Sno = no;
Sname = name;
Speace = peace;
Sfinale = finale;
Stotal = total;
}
void Score :: Count()
{
Stotal =(int) (Speace * Rate + Sfinale * (1- Rate));
}
void Score :: ShowScore()
{
cout << Sno << "\t" << Speace << "\t" << Sfinale << "\t" << Stotal << endl;
}
//main.cpp
#include<iostream>
#include"Score.h"
int main()
{
Score ClassScore1[3];
Score ClassScore2[3] = { Score(20190101,"zhangsan",80,79),
Score(20190102,"lisi",90,85),
Score(20190103,"wangwu",70,55)};
for(int i = 0;i < 3;i++)
{
ClassScore2[i].Count();
}
for(int i = 0;i < 3;i++)
{
ClassScore2[i].ShowScore();
}
}
四、动态对象
//在之前的Score.h 文件里增加这个函数
//Score.h
void Score :: SetScore(long no,char * name,int peace,int finale, int total)
{
Sno = no;
Sname = name;
Speace = peace;
Sfinale = finale;
Stotal = total;
}
//main.cpp
#include<iostream>
#include"Score.h"
int main()
{
Score * ClassScore;
ClassScore = new Score[3];
ClassScore[0].SetScore(20190101,"zhangsan",80,79),
ClassScore[1].SetScore(20190102,"lisi",90,85),
ClassScore[2].SetScore(20190103,"wangwu",70,55);
for(int i = 0;i < 3;i++)
{
ClassScore[i].Count();
}
for(int i = 0;i < 3;i++)
{
ClassScore[i].ShowScore();
}
delete [ ] ClassScore;
return 0;
}
运行结果与之前的截图相同。
PS:在建立动态对象数组时,要调用构造函数,调用的次数与数组的大小相同,删除的时候要调用析构函数,调用的次数与数组的大小相同。
五、this指针
概念:this指针是一个系统预定义的特殊指针,指向当前对象 ,表示当前对象的地址。
在函数SetTime()中,函数体中这三行是等效的。
void Clock :: SetTime(int h,int m,int s)
{
H = h; M = m; S = s;
this -> H = h; this -> M = m; this -> S = s;
(* this).H = h; (*this).M = m; (*this).S = s;
}
PS:
(1)this指针不是调用对象的名称,而是指向对象的指针的名称。
(2)this的值不能改变,他总是指向当前调用对象。
六、组合对象
概念:组合概念体现的是一种包含与被包含的关系,即在逻辑上A是B的一部分。一个类内嵌其他类的对象作为成员,将对象嵌入到类中的这样一种描述复杂类的方法叫做类的组合,一个含有其他类对象称为组合类,组合类的对象称为组合对象。
我们以计算火车旅途时间的组合类来看。
类名 | 成员名 | |
TrainTrip | Clock StartTime | H,M,S |
SetTime(),ShowTime() | ||
Clock EndTime | H,M,S | |
SetTime(),ShowTime() | ||
char * TrianNO | ||
char * TripTime() |
类TrainTrip的构成与成员
//Clock.h
#include<iostream>
using namespace std;
class Clock
{
public:
Clock(int h = 0,int m = 0,int s = 0)
{
this -> H = (h > 0 && h < 24) ? h : 0;
this -> M = (m > 0 && m < 60 ) ? m : 0;
this -> S = (s > 0 && s < 60 ) ? s : 0;
}
void SetTime(int h,int m,int s)
{
this -> H = (h > 0 && h < 24) ? h : 0;
this -> M = (m > 0 && m < 60 ) ? m : 0;
this -> S = (s > 0 && s < 60 ) ? s : 0;
}
void ShowTime()
{
cout << H << ":" << M << ":" << S << endl;
}
int GetH()
{
return H;
}
int GetM()
{
return M;
}
int GetS()
{
return S;
}
private:
int H;
int M;
int S;
};
//TrainTrip.h
#include<iostream>
#include"Clock.h"
using namespace std;
class TrainTrip
{
public:
TrainTrip(char * trainno,Clock s,Clock e)//构造函数
{
this -> TrainNo = trainno;
this -> StartTime = s;
this -> EndTime = e;
}
Clock TrainTime()
{
//临时存储小时,分钟,秒
int tH;
int tM;
int tS;
//借位
int carry = 0;
//临时存储时间
Clock tTime;
(tS = EndTime.GetS() - StartTime.GetS() ) > 0 ? carry = 0 : tS += 60,carry = 1;
(tM = EndTime.GetM() - StartTime.GetM() - carry ) > 0 ? carry = 0 : tM += 60,carry = 1;
(tH = EndTime.GetH() - StartTime.GetH() - carry ) > 0 ? carry = 0 : tH += 24;
tTime.SetTime(tH,tM,tS);
return tTime;
}
private:
char * TrainNo; //车次
Clock StartTime; //出发时间
Clock EndTime; //到达时间
};
//main.cpp
#include<iostream>
#include"TrainTrip.h"
using namespace std;
int main()
{
Clock C1 (8,10,10);//定义Clock类的对象
Clock C2(6,1,2);
Clock C3;//定义Clock类对象,存储结果
TrainTrip T1("K16",C1,C2);//定义TrainTrip对象
C3 = T1.TrainTime();
C3.ShowTime();
return 0;
}
运行结果:
时分秒 H,M,S是Clock类的私有成员,在Clock类外无法存取,而在TrainTrip类中需要H,M,S的值,因此在Clock类中提供了一个公有的存取H,M,S值的接口函数GetH(),GetM(),GetS()供TrainTrip类读取H,M,S。
PS:
(1)建立对象时,通过成员类的构造函数对成员对象进行初始化,初始化值在初始化表中提供。
(2)在定义一个组合对象时:
a.成员对象按照在其组合类的声明中出现的次序依次调用各自的构造函数。
b.组合类对象调用组合类构造函数。
c.调用析构函数,析构函数的调用顺序与构造函数相反。
(3)组合类成员对象的访问权限
成员对象 组合类 | public | protected | private |
public | public | 不可访问 | 不可访问 |
protected | protect | 不可访问 | 不可访问 |
private | private | 不可访问 | 不可访问 |
各个成员对象在组合类中的访问控制属性