c++头文件 防卫式声明
#ifndef __CLASSNAME__
#define __CLASSNAME__
...
#endif
本周目标
完成一个复数的类
一个class包含一个class head和一个class body
思考一:
要实现一个复数的类,需要包含哪些数据:
实部和虚部 double类型
so
private:
double re,im
思考二
上面的实部和虚部的数据类型为double,但是如果我要改变数据类型为int怎么办?重新写个类吗?感觉不科学啊?
so
这里引出模板的概念
template<typename T>
class complex
{
public:
...
private:
T re,im
}
用法如下:
complex<double> c1(2.4,1.5);
complex<int> c2(2,6);
思考三
函数为什么有的定义在class body里面,有的定义在class body外面?
定义在class body里面的函数成为inline函数。
简单理解为inline函数处理速度快。
定义在class body外的函数也可以在函数前+inline 声明为inline函数。
但是 需要了解的是,即使你认为声明了inline,但是是不是真是的inline函数,这个由编译器来决定,我们的声明只是告诉编译器,尽量来帮我定义为inline函数
思考四
private和public的作用分别是什么?
private,私有的,用于存放数据,形成封装,不允许外界调用
public ,公有的,主要用来存放函数
在private中以friend 声明一个函数,该函数可以直接调用private中的数据
思考五
什么是构造函数?
当你创建一个对象时,被编译器自动调用来实现创建对象这一目的的函数,就是构造函数
构造函数的函数名称必须与类的名称一致。
构造函数有几个独特的特性:
- 没有返回类型
- 拥有初值列
对应于构造函数,一个类也通常要有析构函数
对于没有指针的类中,通常可以不用写析构函数
构造函数可以有很多个,实现各种不同的创建对象方式。
overloading 函数重载
在函数名的后面加const
double real() const {return re;}
double imag() const {return im;}
若不打算改变数据内容,则最好加上const
参数传递 pass by value vs. pass by reference
pass by value 就是将参数整个传递过去,value假设100个字节,传递过去就是100个字节。
若是pass by reference,就是传引用,引用就相当于一个指针,只传递4个字节
因此,对于参数传递,最好都只传递引用
对于返回值的传递,尽量也返回引用
一个好的类需要注意的事项
- 数据都放在private里
- 参数传递用reference
- 返回值尽量用reference
- class body中的函数,需要加上const的一定要加
- 构造函数要充分利用初值列
typename() 临时对象
类的名称后面直接加小括号,意思是创建临时对象
一个类的实现
- 防卫式声明
#ifndef __CLASSNAME__
#define __CLASSNAME__
......
#endif
- 建立class body
class complex
{
}
- 在private中定义数据
- 定义构造函数
- 定义成员函数和非成员函数
本周作业
为Date类实现如下成员:
- 构造器,可以初始化年、月、日。
- 大于、小于、等于(> 、< 、==)操作符重载,进行日期比较。
- print() 打印出类似 2015-10-1 这样的格式。
然后创建两个全局函数:
- 第1个函数 CreatePoints生成10个随机的Date,并以数组形式返回;
- 第2个函数 Sort 对第1个函数CreatePoints生成的结果,将其按照从小到大进行排序。
最后在main函数中调用CreatePoints,并调用print将结果打印出来。然后调用Sort函数对前面结果处理后,并再次调用print将结果打印出来。
思考1
构造器,可以初始化年月日。
这里是一个构造函数,有三个参数:年、月、日,并且设有初值。
Data (int y=2000,int m=1,int d=1)
:year(y),month(m),day(d)
{}
思考2
通过大于小于等于号分别实现日期的比较
对于日期的比较有两种思路:
- 分别从年、月、日开始对比,先对比年,年相同再对比月,月相同再对比日。
- 将年月日串联起来组成一个数字,例如2012-5-1可以转换为20120501,这样对比日期时直接可以用默认的比较符号来实现。
下来分别实现:
方法一
因为大于、小于、等于(> 、< 、==)都是二元运算符,所以将其定义为成员函数
bool operator >(const date&);
bool operator <(const date&);
bool operator ==(const date&);
inline bool
date::operator<(const date& d1)
{
this->year < d1.year || this->year == d1.year&&this->month < d1.month
|| this->year == d1.year&&this->month == d1.month&&this->day < d1.day;
}
inline bool
date::operator>(const date& d1)
{
this->year > d1.year || this->year == d1.year&&this->month > d1.month
|| this->year == d1.year&&this->month == d1.month&&this->day > d1.day;
}
inline bool
date::operator==(const date& d1)
{
this->year == d1.year&&this->month == d1.month&&this->day > d1.day;
}
方法二
int date2int(const date& mydate)
{
return mydate.year * 1000 + mydate.month * 100 + mydate.day;
}
inline bool
date::operator<(const date& d1)
{
return date2int(*this) < date2int(d1);
}
inline bool
date::operator>(const date& d1)
{
return date2int(*this) > date2int(d1);
}
inline bool
date::operator==(const date& d1)
{
return date2int(*this) ==date2int(d1);
}
思考3
能够打印出类似2015-10-1这样的格式
对<<进行操作符重载
ostream& operator<<(ostream& os, const date& x)
{
return os << x.get_y() << "-" << x.get_m << "-" << x.get_d << endl;
}
思考4
创建全局函数,随机生成10个date,以数组形式返回
随机生成10组数
产生随机数有rand函数和srand函数
srand函数用于设定rand的随机种子
date* CreatePoints()
{
srand(time(NULL));
date date_array[date_num];
for (int i = 0; i <=date_num; ++i)
{
date_array[i] = date(rand() % 10 + 2000, rand() % 12 + 1, rand() % 31 + 1);
}
return date_array;
}
对数组进行排序
考虑使用sort
void Sort(date* mydate)
{
sort(mydate, mydate + date_num);
}
网友评论