美文网首页
Boolan C++面向对象高级编程(上)第一周

Boolan C++面向对象高级编程(上)第一周

作者: kwangxn | 来源:发表于2017-10-03 20:26 被阅读0次

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中的数据

思考五

什么是构造函数?
当你创建一个对象时,被编译器自动调用来实现创建对象这一目的的函数,就是构造函数
构造函数的函数名称必须与类的名称一致。
构造函数有几个独特的特性:

  1. 没有返回类型
  2. 拥有初值列

对应于构造函数,一个类也通常要有析构函数
对于没有指针的类中,通常可以不用写析构函数

构造函数可以有很多个,实现各种不同的创建对象方式。
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个字节
因此,对于参数传递,最好都只传递引用

对于返回值的传递,尽量也返回引用

一个好的类需要注意的事项

  1. 数据都放在private里
  2. 参数传递用reference
  3. 返回值尽量用reference
  4. class body中的函数,需要加上const的一定要加
  5. 构造函数要充分利用初值列

typename() 临时对象

类的名称后面直接加小括号,意思是创建临时对象

一个类的实现

  1. 防卫式声明
#ifndef __CLASSNAME__
#define __CLASSNAME__
......
#endif
  1. 建立class body
class complex
{

}
  1. 在private中定义数据
  2. 定义构造函数
  3. 定义成员函数和非成员函数

本周作业

为Date类实现如下成员:

  1. 构造器,可以初始化年、月、日。
  2. 大于、小于、等于(> 、< 、==)操作符重载,进行日期比较。
  3. print() 打印出类似 2015-10-1 这样的格式。

然后创建两个全局函数:

  1. 第1个函数 CreatePoints生成10个随机的Date,并以数组形式返回;
  2. 第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

通过大于小于等于号分别实现日期的比较
对于日期的比较有两种思路:

  1. 分别从年、月、日开始对比,先对比年,年相同再对比月,月相同再对比日。
  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);
}

相关文章

网友评论

      本文标题:Boolan C++面向对象高级编程(上)第一周

      本文链接:https://www.haomeiwen.com/subject/bnltyxtx.html