发布日期:2015-12-29 09:23 来源: 标签: 编程语言 C++教程 C++类及构造函数 C++类成员及封装性
本章我们主要是了解C++类的构成;掌握声明类的方法,类和类的成员的概念以及定义对象的方法;掌握成员函数的定义;熟悉构造函数和析构函数;了解C++的封装性,下面我们就做一下具体讲解,希望大家多多支持中国站长网络学院。
一、C++程序开发过程
C++程序开发过程如图1.1所示。
C++程序开发过程与其他高级语言语言源程序开发过程一样,都必须先经过编辑、编译和连接过程,最后生成可执行的代码后才能运行。程序开发过程基本步骤如下:
(1) 编辑
编辑是将编写好的C++源程序输入到计算机中,生成磁盘文件的过程。磁盘文件名字要用扩展名.cpp,例如:File.cpp。
(2) 编译
编译是通过编译器将程序的源代码(.cpp)转换成为机器代码的形式,称为目标代码,即机器语言指令,这时产生的文件扩展名为. obj。如:将源文件File.cpp编译后,生成目标文件File.obj。但这仍然不是一个可执行的程序,因为目标代码只是一个个的程序块,需要相互连接成为一个适应操作系统环境的程序整体。为了把它转换为可执行程序,必须进行连接。
(3) 连接
连接是编译的最后一个过程,它将用户程序生成的多个目标代码文件和系统提供的库文件(.lib)中某些代码连接在一起,经过这种连接处理,生成一个可执行文件,存储这个可执行文件的扩展名为.exe。如:File.obj文件经连接处理后,生成可执行文件File.exe。
(4) 运行
最后是运行程序。运行可执行文件的方法很多,一般在编译系统下有运行功能,可通过选择菜单项的方式实现。

程序在被编译、连接的过程中,难免会出现错误,这时系统会给出致命错和警告错的提示,这时需要返回上一步过程中,对源程序进行修改,直至没有错误提示为止。对于程序中存在的致命错误必须要进行修改,否则,系统不能生成可执行文件。程序中存在警告错误时,虽然系统也会生成可执行文件,但是一般要求修改错告错误后再再去运行可执行文件,因为有的错告错误会造成结果的错误。
编译过程主要是进行词法分析和语法分析的过程。程序的运行,是对算法的验证。程序被 运行后,一般在屏幕上显示出运行结果。用户可以根据运行结果来判断程度是否有算法上的错误。
二、基本概念
1) C++类的构成
  定义类的一般形式
class 类名

        private:
               //私有类型数据成员和成员函数
  protected:
              //保护类型数据成员和成员函数
  public:
             //公有类型数据成员和成员函数
} ;
(2) 成员函数的定义
定义成员函数的一般形式
返回值类型 类名::成员函数名(参数表)
{
  函数体;
}
其中“::”是作用域运算符
例:void CArea::square(int vx, int vy)
其中:void  为函数返回值类型
    CArea 为类名
   :: 为作用域运算符
    square 为成员函数名
    int vx, int vy 为参数列表
(3) 定义对象 
对象定义的一般形式
<类名> <对象名>(<初值表>);
例:class CDate
        { int Year;
              ……
         };
          ……
          CDate  myBirthday(1988,10,1),*day; 
  其中: CDate 为类名
    myBirthday 为对象名
    (1988,10,1)  为初值表
    *day 为指向CDate类的指针
(4)构造函数与析构函数
构造函数
构造函数应具有以下特点,并遵循下列规则:
1. 构造函数名与类的名称必须相同。
2. 构造函数没有返回值,因此也没有函数类型的说明。
3. 类中既可包含多个构造函数,也可没有构造函数,此时编译系统会自动使用缺省值。
4. 拷贝构造函数可利用已有的对象来建立一个类中的新对象。
5. 构造函数是由系统自动调用来给对象进行初始化的。
构造函数一般格式:
  构造函数名(类型1 形参1,类型2 形参2,……)
例:类中声明构造函数
class CA
{
     //……
public:
    CA() { } ;//声明无参数的构造函数
    CA(int rx,int ry); //声明带两个整型参数的构造函数
    CA(float rr) {r=rr;} //声明带一个浮点参数的构造函数 
    CA(floxt rr,char ra[ ]) //声明带两个参数的构造函数 
};
 定义对象的一般格式:
  类名 对象名(实参1,实参2,……)
析构函数
1. 析构函数的名称必须是“~”符号加上类     名称。
2. 析构函数没有返回值,也不能接受任何参数,因此也没有函数类型说明。
3. 一个类仅有一个析构函数,如果类中未定义析构函数,系统会自动加上一个完全不做任何事的析构函数。
4. 析构函数不能重载。 
 当对象的生命期结束时,会自动执行析构函数。
三、程序例题
例1.1  显示日期。
程序实现:
#include"iostream.h"
 class  tdate
   { private:                        //成员函数声明
int month;
int day;
int year;
public:
        void set(int, int, int);           //置日期值
        int  isleapyear( );             //判是否闰年
        void print( );                 //输出日期值
    };
void  tdate::set(int m, int d, int y)
{   month = m;
day = d;
year = y;
        }
int tadte::isleapyear( )
{  return(year%4==0&&year%100!=0||year%400==0);
void print( )
{cout << month <<"/"<< day <<"/"<< year << endl;}
       }
void main( )
{   tdade a;                      //定义类对象
a.set(2, 4, 2006);
a.print( );
   }
程序运行结果为:
屏幕显示:          2/4/2006
例1.2  显示时钟。
程序实现:
#include"iostream.h"
class  Clock                        //定义时钟类
{  private:
int Hour, Minute, Second;
public:
    Clock( );                 //构造函数
    void SetTime(int newh, int newm, int news);
        void ShowTime( );
};
Clock::Clock( )                   //构造函数实现
{  Hour = 0;
 Minute = 0;
 Second = 0;
}
void Clock::SetTime(int newh, int newm, int news)
{  Hour = newh;
     Minute = newm;
     Second = news;
}
void Clock::ShowTime( )
{ cout << Hour <<":"<< Minute <<":"<< Second << endl;}
void main( )
{  Clock  myclock;
     cout <<"First time set and output: "<< endl;
     myclock.ShowTime( );
     cout <<"Second time set and output: "<< endl;
     myclock.SetTime(8, 30, 30);  //设置时间为8:30:30
     myclock.ShowTime( );
}
程序运行结果:

例1.3  自定义拷贝构造函数举例。
程序实现:
#include < iostream.h >
#include < string.h >
class String                   //声明一个字符串类
{   int length;              //字符串长度
 char *str;              //指向字符串指针
public:
  String(char *);          //声明构造函数
  String(const String &p);  //声明自定义拷贝构造函数
  void Show( )           //显示字符串
   {  cout << str << endl; }
};
String::String(char *s)      
{ if(s)
  {  length = strlen(s);
 str = new char[length+1];
 strcpy(str, s);
  }
else
  {  length = 0;
 str = 0;
  }
}
String::String(const String &p)
{ length = p.length;
str = new char[length+1];
strcpy(str, p.str);
}
void main( )
{ String str1("This a constructing. ");
String str2(str1);
cout <<"str1: ";
str1.Show( );
cout <<"拷贝后\nstr2: ";
str2.Show( );
}
程序运行结果为:

由上面的程序运行结果中可以看出,程序第一步是创建对象str1,这时系统自动调用构造函数String(char *),给对象str1的str进行初始化,使str1的数据成员str ="This a constructing. "。程序第二步是创建对象str2,它使用的方法是:用一个已知的对象str1来初始化这个被创建的同类对象str2。因此,在创建对象str2时,系统自动调用拷贝构造函数String(const String &p),将对象str1的str的值拷贝给了对象str2的str。因此str2的数据是拷贝str1的数据,所以最后的结果是一样的。
例1.4  在例题1.3的基础上,加上析构函数,体会析构函数的使用。
#include < iostream.h >
#include < string.h >
class String                     //声明一个字符串类
{   int length;                //字符串长度
  char *str;                 //指向字符串指针
public:
 String(char *);              //声明构造函数
 String(const String &p);      //声明自定义拷贝构造函数
 void Show( )               //显示
   {  cout << str << endl; }
 ~String( );
};
String::String(char *s)      
{ if(s)
 {  length = strlen(s);
str = new char[length+1];
strcpy(str, s);
 }
else
 { length = 0;
str = 0;
 }
}
String::String(const String &p)
{  length = p.length;
str = new char[length+1];
strcpy(str, p.str);
}
String::~String( )
{ cout <<"调用析构函数 撤消对象"<< endl;
delete str;
}
void main( )
{ String str1("This a constructing. ");
String str2(str1);
cout <<"str1: ";
str1.Show( );
cout <<"拷贝后\nstr2: ";
str2.Show( );
}
程序运行结果为:

可以从上面的结果看出,当程序结束时,析构函数被调用两次,撤消对象str1和str2。
例1.5  一个“帮教派对”类tutorpair中,包含有学生类对象和老师类对象。
#include"iostream.h"
class student
{ public:
student( )
{  cout <<"constructing student.\n";
semesHours = 100;
gpa = 3.5;
        }       
~student( )
{cout <<"destructing student.\n";}
protected:
int semesHours;
float gpa;
 };   
 class  teacher
{ public:
teacher( )
{cout <<"constructing teacher.\n";}
~teacher( )
{cout <<"destruching teacher.\n";}
};
class  tutorpair
{public:
tutorpair( )
{  cout <<"constructing tutorpair.\n";
nomeetings = 0;
        }
~tutorpair( )
{cout <<"destructing tutorpair.\n";}
protected:
student student;
teacher teacher;
int nomeetings;
};
void main( )
{  tutorpair tp;
cout <<"back in main.\n";
 }                                
程序运行结果为:
constructing  student.  
constructing  teacher.  
Constructing  tutorpair.
back in main.          
destructing tutorpair. 
destruching teacher.   
destructing  student.
在这个例子中,着重说明构造函数和析构函数的用法。主函数main运行开始时,遇到要创建tutirpir类的对象,于是调用其构造函数tutorpair( ),该构造启动时,首先分配对象空间(包含一个student对象、一个teacher对象和一个int型数据),然后根据在类中声明的对象成员的次序依次调用其构造函数。这里先调用studert( )构造函数,后调用teacher( )构造函数,最后才执行它自己的构造函数的函数体。按照这个顺序,分别产生运行结果的第一、第二、第三行输出。当执行完tutorpair( )构造函数后,控制回到主函数中,于是得到第四行输出。当主函数运行到结束的花括号处时,析构函数依次被调用,其顺序正好与构造函数相反。于是得到后三行输出。
例1.6   定义一个学生类,学生数据有学号、成绩,成员函数有建立学生信息、查找成绩和输出显示。要求:建立5个学生对象,输入信息后,可根据学号,输出学生成绩。
程序实现:
#include"iostream.h"
class Student             //定义学生类
{    int Num;         //存放学号
   float Score;       //存放成绩
public:
   void Set( );       //建立信息函数
   int Find(int n);    //查找函数,找到返回1,否则返回0
   void Display( );   //显示信息
};
void Student::Set( )
{  cin >> Num >> Score; } //输入信息
int  Student::Find(int n)
{ if(Num==n) return 1;   //学号相等返回1
else  return 0;
}
void Student::Display( )    //输出信息到屏幕
{ cout <<"学号: "<< Num <<"成绩: "<< Score << endl;}
void main( )
{   Student stu[5];      //建立对象数组
      cout <<"请输入学生学号, 成绩: "<< endl;
  for(int i = 0; i < 5; i++)
   {  cout <<"第"<< i+1 <<"位同学: ";
  stu[i].Set( );    //调用建立信息函数
    }
  for(i = 0; i < 5; i++)
 stu[i].Display( );  //输出显示
      int n, flag = 0;
  cout <<"请输入要查找同学学号:";
  cin >> n;
    for(i = 0; i < 5; i++)
   { if(stu[i].Find(n)==1)  //查找
  {  stu[i].Display( );
        flag = 1;
 break;
  }
   }
  if(flag==0)cout<<"没有找到该学生!"<<endl;
}
程序运行结果:

在该题中先定义学生对象数组,循环调用建立信息函数Set( ),建立5位学生的信息,后调用Display( )函数将信息输出显示。然后,根据输入的学号,调用Find( )查找函数,查找符合学号的学生绩,并输出。

相关评论

专题信息
    C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。C++支持多种编程范式 --面向对象编程、泛型编程和过程化编程。最新正式标准C++于2014年8月18日公布。 其编程领域众广,常用于系统开发,引擎开发等应用领域,是至今为止最受广大程序员受用的最强大编程语言之一,支持类:类、封装、重载等特性! 本教程从基础讲解了C++语言,希望对大家有所帮助,望多多支持中国站长网络学院。