第5章类和对象(一)

第5章类和对象(一)
(2008-06-09 08:41:04)
转载
标签:
构造函数
day
date
数据类型
it
	分类:c++学习相关

第5章类和对象

5.1 结构

C++具有丰富的基本数据类型,如:char、int、double等等,使用这些数据类型,已经可以解决很多问题了。

但是,在某些场合,数据类型的集合可以更方便地解决某些问题。例如:数组,它把若干相同类型的数据集合在一起,解决了成批同类型数据的处理问题。

对于由 “若干相同类型的数据集合”构成的数组,由于每个元素的类型都相同,因此,其数组的“整体类型”也就是这个公共的类型了。所以,其处理过程也比较简单,数组中的每一个元素等价于同类型的一个变量,使用下标方法就可以方便地处理数组元素。

在实际问题中,我们往往会碰到“一组数据中的各个数据具有不同类型”的情况。例如,例如,对于处理一个班的学生成绩问题时,每个人都涉及到“姓名、性别、年龄、成绩”的问题,这一组组的数据都有内在联系且类型不同,姓名应为字符型数组,性别应为字符型;年龄应为整型;成绩可为整型或实型。显然不能用一个数组来存放这一组数据。

对于这样的由“若干不同类型的数据集合”而构成的整体,C++称之为结构。结构中,各成员的类型不一定相同,那么该如何表达其“整体类型”呢?

C++提供了一种自定义数据类型的机制,即允许程序员自己创造数据类型。这种可以自定义数据类型的方法,可以为我们解决复杂问题提供了方便。

C++内部数据类型的名称全是由小写字母构成的,为了与之区别,我们一般将自定义数据类型的名称以大写字母开头。

一、结构类型的定义

定义某个特定结构类型,采用以下一般形式:

struct 结构名

{

类型说明符 成员名1;

类型说明符 成员名2;

类型说明符 成员名3;

类型说明符 成员名4;

……      ……

};

   例如:

struct Stu

{

char name[20];

char sex;

int age;

float score;

};

注意:在括号后的分号是不可少的。

结构类型定义好之后,即可用这个类型去进行变量说明。这时,被说明的变量,是由数目固定的有序变量的集合,结构中的每一个变量的类型可能是不相同的。由此可见,结构是一种复杂的数据类型。

 

二、结构类型变量的说明

说明结构变量有以下三种方法。以上面定义的stu为例来加以说明。

1)先定义结构,再说明结构变量。这是最常用的方法,如:

struct Stu

{

char name[20];

char sex;

int age;

float score;

};

Stu boy1,boy2;

说明了两个变量boy1和boy2为stu结构类型。

 

2)在定义结构类型的同时说明结构变量。例如:

struct Stu

{

char name[20];

char sex;

int age;

float score;

}boy1,boy2;

 

3)直接说明结构变量。例如:

struct

{

char name[20];

char sex;

int age;

float score;

}boy1,boy2;

 

成员也可以又是一个结构,即构成了嵌套的结构。例如:

struct Date

{

int month;

int day;

int year;

};

Struct

{

char name[20];

char sex;

Date birthday;

double score;

}boy1,boy2;

 

三、结构变量中成员名的使用

1、成员名可与程序中其它变量同名,互不干扰。

2、表示结构变量成员的一般形式是:结构变量名.成员名

例如:boy1.num 即第一个人的学号 boy2.sex即第二个人的性别。

3、如果成员本身又是一个结构则必须逐级找到最低级的成员才能使用。

例如:boy1.birthday.month 即第一个人出生的月份

4、给结构变量的赋值就是给各成员赋值。可用输入语句或赋值语句来完成。

例题:日期结构

#include<iostream.h>

 

struct Date

{

int year;

int month;

int day;

};

 

void print(Date);

bool isLeapYear(Date d);

 

void main()

{

Date d;

d.year = 2000;

d.month = 12;

d.day = 6;

if(isLeapYear(d))  print(d);

}

 

void print(Date s)

{

 cout<<s.year<<'-'<<s.month<<'-'

<<s.day<<endl;

}

 

bool isLeapYear(Date d)

{

return(d.year%4==0&&

d.year%100!=0)||(d.year%400==0);

}

结构类型的定义还是存在局限性,它只定义了一组不同类型数据的集合,而没有定义相关操作,如赋值、输出等。特别是在一个程序员接手另一个程序员工作的时候,这种对结构的理解和编写相关操作的负担加重了。

为了减轻其它程序员的编程负担,我们需要把结构类型的定义做得更全面些,使它不仅仅有数据的定义,而且有操作的定义,这就是类。

 

5.2 类与对象

一、什么是类

类是一种由程序员自己创造的复杂数据类型。具体说:类是一个数据类型;类类型通常很复杂;类类型是由程序员自己创造的。

程序员将各种彼此相关的各种类型的数据和与这些数据相关的操作(函数)封装在一起的,便创造了一个具体类类型。

通俗地说,类类型中包含了若干数据,还包含了若干函数。

二、类类型的定义

采用C++提供的自定义数据类型的机制,由程序员自己创造数据类型的方法,完成类类型的定义。

类类型的定义一般又两部分构成:说明部分和实现部分。

说明部分是用来说明该类中的成员,包含数据成员的说明和成员函数的说明。成员函数是用来对数据成员进行操作的,又称为“方法”。

实现部分是用来对成员函数的定义。

概括说来,说明部分将告诉使用者“干什么”,而实现部分是告诉使用者“怎么干”。

1、类的一般定义格式如下:

class 类名

{

   public:

       数据成员或成员函数的说明

   private:

       数据成员或成员函数的说明

   protected

       数据成员或成员函数的说明

};

各个成员函数的实现

 

2、定义类时应注意的事项

A、class是定义类类型的关键字,“类名”是标识符,通常用大写字母开始的字符串作为类名。

B、花括号内是类的说明部分,说明该类包含哪些数据成员和哪些成员函数。

C、类中的数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等。

D、另一个类的对象,可以作该类的成员。当一个类的对象为这个类的成员时,如果另一个类的定义在后,需要提前说明。

E、在类体中不允许对所定义的数据成员进行初始化,因为类的定义只是在创造一个类型而已,而不是在说明“变量”。

 

3、类成员的访问控制

A、从访问权限上来分,类的成员又分为:公有的(public)、私有的(private)和保护的(protected)三类。

B、公有成员用public来说明,公有部分往往是一些操作(成员函数),它是提供给用户的接口。这部分成员可以在程序中引用。

C、私有成员用private来说明,私有部分通常是一些数据成员,这些成员是用来描述该类中的对象的属性的,只有成员函数或经特殊说明的函数才可以引用它们,它们是被用来隐藏的部分。

D、保护成员用protected来说明,在大多数情况下,类的保护成员具有私有成员的性质,但在派生类的成员函数而言,它具有公有成员的性质。

关键字public、private和protected被称为访问权限修饰符或访问控制修饰符,用它们来说明类成员的访问权限。它们在类体内出现的先后顺序无关,并且允许多次出现。

一般地,在类体内先说明公有成员,它们是用户所关心的,后说明私有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,由小至大说明,这样可提高时空利用率。

经常习惯地将类定义的说明部分或者整个定义部分(包含实现部分)放到一个头文件中。

4、类成员函数的实现

在类类型的定义中,“各个成员函数的实现”是类定义中的实现部分,这部分包含所有在类体内说明的函数的定义。

返回值的类型 类名::成员函数名(参数表)

{

函数体

}

其中“::”叫作用域运算符。

如果一个成员函数的类体内定义了,实现部分将不出现。如果所有的成员函数都在类体内定义,则实现部分可以省略。

例题:日期类的定义(说明部分+实现部分)

class Date

{

public:

    void set(int y,int m,int d);// 赋值操作

    boolisLeapYear();       // 判断闰年

    voidprint();              // 输出日期

private:

    int year,month,day;

};

 

void Date::set(int y,int m,int d)

{

    year=y;

    month=m;

    day=d;

}

 

bool Date::isLeapYear()

{

    return(year%4==0&&year%100!=0)||

(year%400==0);

}

 

void Date::print()

{

    cout<<year<<'-'<<month<<'-'<<day<<endl;

}

 

三、对象

回忆变量的定义方法:double x,y,z;

1、类似于用基本数据类型来说明变量的方法,我们可以用自己创建的类类型来说明“变量”,此时的“变量”叫对象。

2、访问对象的公有成员:

当用自己创建的类类型来说明“对象”以后,程序中就可以用运算符“.”来引用其公有成员,引用的方式如下:

对象名.公有数据成员名

对象名.公有成员函数名(实参表)

对“对象”中数据成员的赋值和数据传递一般都是通过成员函数来进行的。

#include<iostream.h>

 

class Date

{

public:

    void set(int y,int m,int d);// 赋值操作

    boolisLeapYear();       // 判断闰年

    voidprint();              // 输出日期

private:

    int year,month,day;

};

 

void Date::set(int y,int m,int d)

{

    year=y;

    month=m;

    day=d;

}

 

bool Date::isLeapYear()

{

    return(year%4==0&& year%100!=0)

||(year%400==0);

}

 

void Date::print()

{

    cout<<year<<'-'<<month<<'-'<<day<<endl;

}

 

void main()

{

    Date d;

    d.set(2000,12,6);

    if(d.isLeapYear())

        d.print();

}

 

指向对象的指针的成员表示如下:

对象指针名->公有数据成员名

对象指针名->公有成员函数名(实参表)

 

 注意:->用于表示指向对象的指针的成员

       . 用于表示一般对象的成员

下列表示是等价的:

对象指针名->公有数据成员名

(*对象指针名).公有数据成员名

 


5.3 对象的初始化

一、构造函数和析构函数

1、什么是构造函数

在进行类的定义时(程序员自己创建类类型),不能给类中数据进行初始化,因为在这一过程中,仅仅是创建一个类类型而已。就好象系统在创造int作为整型的时候,它也不能先给整型数据进行初始化。

我们可以使用系统的基本数据类型来说明变量,我们也可以使用自己创建的类类型来创建对象。

在使用系统的基本数据类型来说明变量时,可以对该变量进行初始化,如:intx=5;

当我们使用自己创建的类类型来创建对象时,可不可以采用类似的方式进行初始化呢?回答是肯定的。

要求:对象的初始化工作须通过构造函数来完成。

2、构造函数的特点:

1)构造函数是类的一个成员函数,但有其特殊性。

2)构造函数的函数名与类名相同。

3)构造函数不能有返回值。

4)构造函数的主要功能是完成对象的初始化工作。

5)构造函数可以重载。

在使用类名创建对象的时候,系统会自动调用构造函数,实现其“完成对象的初始化工作”的功能。

回忆例题:

#include<iostream.h>

 

class Date

{

public:

    void set(int y,int m,int d);// 赋值操作

    boolisLeapYear();       // 判断闰年

    voidprint();              // 输出日期

private:

    int year,month,day;

};

 

void Date::set(int y,int m,int d)

{

    year=y;

    month=m;

    day=d;

}

 

bool Date::isLeapYear()

{

    return(year%4==0&& year%100!=0)

||(year%400==0);

}

 

void Date::print()

{

    cout<<year<<'-'<<month<<'-'

<<day<<endl;

}

 

void main()

{

    Dated;                             //创建对象

    d.set(2000,12,6);

//调用set函数实现对象初始化

//注意私有数据是不好直接赋值的

    if(d.isLeapYear())

        d.print();

}

 

使用构造函数改写以上程序

#include<iostream.h>

 

class Date

{

public:

    Date(int y,int m,int d);

//构造函数,与类同名,不能指定返回值

    boolisLeapYear();   // 判断闰年

    voidprint();          // 输出日期

private:

    int year,month,day;

};

 

Date::Date(int y,int m,int d)

{

    year=y;

    month=m;

    day=d;

}

 

bool Date::isLeapYear()

{

    return(year%4==0&& year%100!=0)

||(year%400==0);

}

 

void Date::print()

{

    cout<<year<<'-'<<month<<'-'

<<day<<endl;

}

 

void main()

{

    Date d(2000,12,6);

//创建对象时,自动调用构造函数

   if(d.isLeapYear())

        d.print();

}

1、什么是析够函数

析构函数也是特殊的类成员函数,它没有返回类型,没有参数,也没有重载,不能随意调用,只有在类对象的生命期结束的时候,由系统自动调用。

1)析够函数是类的一个特殊成员函数。

2)析够函数的函数名取“~类名”。

3)析够函数不能有返回值,也不能有函数参数。

4)析够函数的主要功能是在对象消失时,执行如释放内存等清理工作。

5)在对象消失时,析够函数会被自动调用。

例题:

#include<iostream.h>

 

class Date

{

public:

    Date(int y,int m,int d); // 构造函数

    ~Date();               // 析构函数

    voidprint();           // 输出日期

private:

    int year,month,day;

};

 

Date::Date(int y,int m,int d)

{

    year=y;

    month=m;

    day=d;

    cout<<"Constructorcalled."<<endl;

}

 

Date::~Date()

{

    cout<<"Destructorcalled"<<endl;

}

 

void Date::print()

{

    cout<<year<<'-'<<month<<

        '-'<<day<<endl;

}

 

void main()

{

    Date today(2007,10,17);

    Date tomorrow(2007,10,18);

   cout<<"today is";

    today.print();
 



原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124576.html