文章目录
1.时钟程序(多文件)
Clock.h头文件
#ifndef _CLOCK_H_
#define _CLOCK_H_
struct Time{
int hour;
int minute;
int second;
};
void set(Time* p,int h,int m,int s);
void tick(Time* p);
void show(Time* p);
void run(Time* p);
#endif
Clock.cpp实现文件
#include "Clock.h"
#include <iostream>
using namespace std;
#include <ctime>
void set(Time* p,int h,int m,int s)
{
p->hour = h;
p->minute = m;
p->second = s;
}
void tick(Time* p)
{
time_t t = time(NULL);
while(time(NULL) == t){};
if(++(p->second) >= 60)
{
p->second = 0;
if(++(p->minute) >= 60)
{
p->minute = 0;
if(++(p->hour) >= 24)
{
p->hour = 0;
}
}
}
}
void show(Time* p)
{
//回到行开头,覆盖上次时间,而不是在上次时间后面显示
cout<<'\r';
if(p->hour < 10)
{
//小于10表示只有一位数,前面补0
cout<<0;
}
cout<<p->hour<<':';
if(p->minute < 10)
{
cout<<0;
}
cout<<p->minute<<':';
if(p->second < 10)
{
cout<<0;
}
//cout输出到缓冲区,缓冲区man后显示在终端
//flush表示立即显示
cout<<p->second<<flush;
}
void run(Time* p)
{
for(;;)
{
tick(p);
show(p);
}
}
main.cpp
#include "Clock.h"
int main()
{
Time t;
set(&t,10,45,50);
run(&t);
}
执行结果:
root@host:/home/LinuxShare/004.c++/day08# g++ *.cpp
root@host:/home/LinuxShare/004.c++/day08# ./a.out
10:46:40
1.1.修改结构中变量名称
如果需要将Time结构中的变量名称做修改。
struct Time{
int hour;
int minute;
int second;
};
修改为:
struct Time{
int hour;
int min; //原变量名:minute
int sec; //原变量名:second
};
那么函数中的变量名称也需要随着更改。具体需要更改哪些函数呢?如果其他开发人员也使用到了Clock.h头文件,那么变更之处将不可控。
1.2.将函数放入结构中,变成结构的成员函数
这样更改的好处:
(1)成员变量修改时,可以明确需要修改的函数都是成员函数,两者同时修改即可;
(2)如果其他结构中也有同名函数,不冲突,不影响使用。
Clock.h
#ifndef _CLOCK_H_
#define _CLOCK_H_
struct Time{
int hour;
int min; //变量名修改
int sec; //变量名修改
void set(Time* p,int h,int m,int s);
void tick(Time* p);
void show(Time* p);
void run(Time* p);
};
#endif
Clock.cpp
#include "Clock.h"
#include <iostream>
using namespace std;
#include <ctime>
//类型名::成员函数
void Time::set(Time* p,int h,int m,int s)
{
p->hour = h;
p->min = m; //变量名修改
p->sec = s; //变量名修改
}
//类型名::成员函数
void Time::tick(Time* p)
{
time_t t = time(NULL);
while(time(NULL) == t){};
if(++(p->sec) >= 60) //变量名修改
{
p->sec = 0; //变量名修改
if(++(p->min) >= 60) //变量名修改
{
p->min = 0; //变量名修改
if(++(p->hour) >= 24)
{
p->hour = 0;
}
}
}
}
//类型名::成员函数
void Time::show(Time* p)
{
cout<<'\r';
if(p->hour < 10)
{
cout<<0;
}
cout<<p->hour<<':';
if(p->min < 10) //变量名修改
{
cout<<0;
}
cout<<p->min<<':'; //变量名修改
if(p->sec < 10) //变量名修改
{
cout<<0;
}
cout<<p->sec<<flush; //变量名修改
}
//类型名::成员函数
void Time::run(Time* p)
{
for(;;)
{
tick(p);
show(p);
}
}
main.cpp
#include "Clock.h"
int main()
{
Time t;
t.set(&t,10,45,50); //变量.成员
t.run(&t); //变量.成员
}
1.3.成员函数中的参数Time* p
多余
在调用成员函数时,程序会自动把结构变量的地址传过来,可以通过this指针来使用这个地址,this是内部自动定义。
Clock.h
#ifndef _CLOCK_H_
#define _CLOCK_H_
struct Time{
int hour;
int min;
int sec;
void set(int h,int m,int s);
void tick();
void show();
void run();
};
#endif
Clock.cpp
#include "Clock.h"
#include <iostream>
using namespace std;
#include <ctime>
//类型名::成员函数
void Time::set(int h,int m,int s)
{
this->hour = h; //使用this
this->min = m; //使用this
this->sec = s; //使用this
}
//类型名::成员函数
void Time::tick()
{
time_t t = time(NULL);
while(time(NULL) == t){};
if(++(this->sec) >= 60) //使用this
{
this->sec = 0; //使用this
if(++(this->min) >= 60)//使用this
{
this->min = 0; //使用this
if(++(this->hour) >= 24) //使用this
{
this->hour = 0; //使用this
}
}
}
}
//类型名::成员函数
void Time::show()
{
cout<<'\r';
if(this->hour < 10) //使用this
{
cout<<0;
}
cout<<this->hour<<':'; //使用this
if(this->min < 10) //使用this
{
cout<<0;
}
cout<<this->min<<':'; //使用this
if(this->sec < 10) //使用this
{
cout<<0;
}
cout<<this->sec<<flush; //使用this
}
//类型名::成员函数
void Time::run()
{
for(;;)
{
tick();
show();
}
}
main.cpp
#include "Clock.h"
int main()
{
Time t;
t.set(10,45,50);
t.run();
}
1.3.成员函数中的this->
多余
成员函数使用当前变量的成员变量,this->
可以不写。
Clock.cpp
#ifndef _CLOCK_H_
#define _CLOCK_H_
struct Time{
int hour;
int min;
int sec;
void set(int h,int m,int s);
void tick();
void show();
void run();
};
#endif
Clock.cpp
#include "Clock.h"
#include <iostream>
using namespace std;
#include <ctime>
//类型名::成员函数
void Time::set(int h,int m,int s)
{
hour = h; //去掉this
min = m; //去掉this
sec = s; //去掉this
}
//类型名::成员函数
void Time::tick()
{
time_t t = time(NULL);
while(time(NULL) == t){};
if(++(sec) >= 60) //去掉this
{
sec = 0; //去掉this
if(++(min) >= 60)//去掉this
{
min = 0; //去掉this
if(++(hour) >= 24) //去掉this
{
hour = 0; //去掉this
}
}
}
}
//类型名::成员函数
void Time::show()
{
cout<<'\r';
if(hour < 10) //去掉this
{
cout<<0;
}
cout<<hour<<':'; //去掉this
if(min < 10) //去掉this
{
cout<<0;
}
cout<<min<<':'; //去掉this
if(sec < 10) //去掉this
{
cout<<0;
}
cout<<sec<<flush; //去掉this
}
//类型名::成员函数
void Time::run()
{
for(;;)
{
tick();
show();
}
}
main.cpp
#include "Clock.h"
int main()
{
Time t;
t.set(10,45,50);
t.run();
}
1.4.成员变量可以任意公开访问修改
修改main.cpp
#include "Clock.h"
int main()
{
Time t;
t.set(10,45,50);
t.hour = 100; //在主函数访问Time机构体中成员并修改
t.run();
}
执行结果:
e/LinuxShare/004.c++/day08#
root@host:/home/LinuxShare/004.c++/day08#
root@host:/home/LinuxShare/004.c++/day08#
root@host:/home/LinuxShare/0
2.类(结构体修改为类)
2.1.结构体stuct修改为类class
其他都不变,更改数据结构为类。
#ifndef _CLOCK_H_
#define _CLOCK_H_
//struct修改为Class
class Time{
int hour;
int min;
int sec;
void set(int h,int m,int s);
void tick();
void show();
void run();
};
#endif
类中成员变量和成员函数,默认都是私有,在main.cpp直接访问,访问了私有变量,导致编译报错。
2.2.类实现时钟程序
Clock.h
#ifndef _CLOCK_H_
#define _CLOCK_H_
class Time{
private:
int hour;
int min;
int sec;
public:
void set(int h,int m,int s);
void tick();
void show();
void run();
};
#endif
Clock.cpp
#include "Clock.h"
#include <iostream>
using namespace std;
#include <ctime>
void Time::set(int h,int m,int s)
{
hour = h;
min = m;
sec = s;
}
void Time::tick()
{
time_t t = time(NULL);
while(time(NULL) == t){};
if(++(sec) >= 60)
{
sec = 0;
if(++(min) >= 60)
{
min = 0;
if(++(hour) >= 24)
{
hour = 0;
}
}
}
}
void Time::show()
{
cout<<'\r';
if(hour < 10)
{
cout<<0;
}
cout<<hour<<':';
if(min < 10)
{
cout<<0;
}
cout<<min<<':';
if(sec < 10)
{
cout<<0;
}
cout<<sec<<flush;
}
void Time::run()
{
for(;;)
{
tick();
show();
}
}
main.cpp
#include "Clock.h"
int main()
{
Time t;
t.set(10,45,50);
t.run();
}
3.对象
对象:类型是“类”的变量。
对象初始化:创建对象时不能像初始化结构一样初始化(原因:private),需要使用构造函数初始化。
3.1.构造函数
构造函数(constructor):跟类名同名的函数称为构造函数,创建对象时构造函数自动被调用,是第一个被调用的成员函数,不用写返回类型(自动调用,即使有返回值也无法取到),常用于初始化成员变量。构造函数只能用于自动调用,一般不主动调用。创建一个对象,只调用一个构造函数(存在多个构造函数的情形),并且只调用一次构造函数。构造函数一般是public成员函数(原因:定义时需调用)。
构造函数传参数:在创建对象(类变量)时直接传参数。如果构造函数中没有形参则不需要传参数。
构造函数重载:一个类中可以存在多个构造函数,并且形参类型不同,构造函数调用时根据形参类型匹配调用。
3.2.初始化列表
初始化:在构造函数的函数头和函数体之间增加初始化信息,(:初始化列表,即冒号+初始化列表)。如果有多项需要初始化,用逗号隔开。常量可以初始化,不能赋值。
构造函数名后初始化时不能初始化数组和结构变量。
A():n(n),d(120.0)
{
cout<<"call A()"<<this<<endl;
}
3.3.形参默认值
如果只想写一个构造函数,要求可以不传参数,可以传两个参数,也可以传三个参数。可通过使用形参默认值实现:在形参中增加默认值,在调用时如果只传一个参数默认传给第一个形参,传两个参数则传给第一个形参和第二个形参。----函数重载。
A(int n=0,d=0.0):n(n),d(120.0)
{
cout<<"call A(int)"<<this<<endl;
}
函数重载过程中,如果两个同名函数,一个无形参,一个有形参但形参有默认值。当不传参数调用时编译器无法区分实际调用哪个函数,编译报错。
3.4.析构函数
析构函数(destructor):在对象被释放的时候自动调用。又名:解构函数、解构器、析构器。
构造函数在创建对象时被自动调用,所以也应为public,创建时可以传参数。但析构函数不是在创建时被调用,无法传参数,所以析构函数没有形参,无法重载。
全局变量,先创建后释放。要保证在main中可以使用,需要在进入main前被创建;为保证main中使用结束才释放,需要在main结束后被释放。
static:静态变量,生命周期被延长。只能被创建一次。
3.5.变量创建和释放顺序
#include <iostream>
using namespace std;
class A{
int n;
public:
A(int n=0):n(n)
{
cout<<this<<' '<<"A("<<n<<")"<<endl;
}
~A()
{
cout<<this<<' '<<"~A("<<n<<")"<<endl;
}
};
void func()
{
A a3(3);
static A a4(4); //静态,声明周期被延长,释放被延迟
}
int main()
{
func();
A a1(1);
}
A a2(2); //全局,进入main函数前需创建
执行结果:
root@host:/home/LinuxShare/004.c++/day08# g++ main.cpp
root@host:/home/LinuxShare/004.c++/day08# ./a.out
0x55f741fd0138 A(2)
0x7ffef59b7534 A(3)
0x55f741fd0140 A(4)
0x7ffef59b7534 ~A(3)
0x7ffef59b7564 A(1)
0x7ffef59b7564 ~A(1)
0x55f741fd0140 ~A(4)
0x55f741fd0138 ~A(2)