201205程序员下午真题

第 1 题

阅读以下说明和流程图,填补流程图中的空缺(1)~(5),将解答填入答题纸的对应栏内。
【说明】
已知数组A[1:n]中各个元素的值都是非零整数,其中有些元素的值是相同的(重复)。为删除其中重复的值,可先通过以下流程图找出所有的重复值,并对所有重复值赋0标记。该流程图采用了双重循环。
处理思路:如果数组A某个元素的值在前面曾出现过,则该元素赋标记值0。例如,假设数组A的各元素之值依次为2,5,5,1,2,5,3,则经过该流程图处理后,各元素之值依次为2,5,0,1,0,0,3。

【流程图】

答案与解析

  • 试题难度:较难
  • 知识点:流程图>流程图
  • 试题答案:
    (1)n-1
    (2)A[i]
    (3)i+1
    (4)A[j]
    (5)A[j]
  • 试题解析:
        在处理大批数据记录时,删除重复记录(关键词重复的记录)是常见的操作。本题源自这种应用。删除重复记录算法可分两步进行。第一步将重复出现的多余元素标记为0;第二步再删除所有的0元素。本题流程图只做第一步处理。
        本流程图采用了对i和j的双重循环,对每个元素A[i],需要查看其后面的各个元素(用A[j]表示)是否与A[i]相同。因此,外层循环应对i=1,n-1进行,从而在(1)处应填“n-1”。内层循环应对j=i+1,n进行,从而在(3)处应填“i+1”。
        在外循环处理中首先应判断A[i]是否已经标记为0,若是则无需进一步处理。因此,(2)处应填“A[i]”。而在内循环处理中首先应判断A[j]是否已经标记为0,若是则无需进一步处理。因此,(4)处应填“A[j]”。如果发现元素重复(即A[i]=A[j]),则需要再将A[j]赋值为0(标记),因此(5)处应填“A[j]”。

第 2 题

阅读以下说明、C程序代码和问题1至问题3,将解答写在答题纸的对应栏内。
【说明1】
设在某C系统中为每个字符型数据分配1个字节,为每个整型(int)数据分配4个字节,为每个指针分配4个字节,sizeof(x)用于计算为x分配的字节数。
【C代码】
     #include <stdio.h>
     #include <string.h>
     int main()
     {   int arr[5]={10, 20, 30};
     char mystr[]="JustAtest\n";
     char *ptr=mystr;

              printf("%d %d %d\n", sizeof(int), sizeof(unsigned int), sizeof(arr));
              printf("%d %d\n", sizeof(char), sizeof(mystr);
     printf("%d %d %d\n", sizeof(ptr), sizeof(*ptr), strlen(ptr));
     return 0;
     }
【说明2】
const是C语言的一个关键字,可以用来定义“只读”型变量。

【问题1】(8分)
    请写出以上C代码的运行结果。
【问题2】(4分)
    (1)请定义一个“只读”型的整型常量size,并将其值初始化为10;
    (2)请定义一个指向整型变量a的指针ptr,使得ptr的值不能修改,而ptr所指向的目标变量的值可以修改(即可以通过ptr间接修改整型变量a的值)。
    注:无需给出整型变量a的定义。
【问题3】(3分)
    某C程序文件中定义的函数f如下所示,请简要说明其中static的作用,以及形参表“const int arr[]”中const的作用。
static int f(const int arr[])
{
  /* 函数体内的语句省略 */
}

答案与解析

  • 试题难度:较难
  • 知识点:C程序设计>C程序设计
  • 试题答案:
    【问题1】
    4 4 20
    1 11
    4 1 10
    【问题2】
    (1)const int size=10;  或 int const size=10;
    (2)int* const ptr=&a;
    【问题3】
    static的作用:说明f足内部函数,只能在本文件中调用它。
    const的作用:在函数f中不能修改数组元素的值,若有修改,编译时会报错。
  • 试题解析:本题考查C语言基础及应用。
    【问题1】
    sizeof是C语言提供的一个关键字,sizeof(x)用于计算为x分配的字节数,其结果与系统或编译器相关。若x是数组名时,用于计算整个数组所占用存储空间的字节数;若x是指针,则无论其指向的目标数据是什么类型,x所占用的存储空间大小都相同(在同一系统或编译环境中);若x是结构体变量或类型,则需要根据系统规定的对齐要求来计算为x所分配空间的字节数。
    根据说明,系统为每个字符型数据分配1个字节,为每个整型(int)数据分配4个字节,为每个指针分配4个字节,那么sizeof(int)、sizeof(unsigned int)是计算整型数据和无符号整型数据的存储空间大小,sizeof(arr)是计算数组arr的字节数,它们的值分别为4、4和20。
    sizeof(char)计算一个字符数据所占用的字节数,根据说明应为1。sizeof(mystr)计算为字符数组mystr分配的空间大小,该数组的大小由字符串"JustAtest\n"决定,该字符串的长度为10,还有一个串尾结束标志字符'/0',因此sizeof(mystr)的值为11。
    ptr是指向字符数组mystr的指针,显然sizeof(ptr)的结果为4。由于ptr指向了一个字符数据,因此sizeof(ptr)的结果为1,函数strlen(ptr)计算ptr所指字符串的长度,结果为10。
    【问题2】
    在C语言中,const关键字的一个作用是限定一个变量的值不能被改变,使用const可以在一定程度上提高程序的安全性和可靠性。
    const int size=10; 或 int const size=10;
    以上代码都可以定义一个“只读”型的整型常量size并将其值初始化为10。
    当const用于修饰指针时,常见的情形如下:
    (1)const修饰的是指针所指向的对象,该对象不可改变,指针变量可改变。
        const int p;       //或 int const p;
    (2)const修饰的是指针,该指针变量不可改变,其指向的对象可改变。
        int const p;
    (3)const修饰的是指针以及指针所指向的对象,都不可改变。
        const int
    const p;
    【问题3】
    关键字static用于修饰函数中的局部变量时,是通知编译器将该变量的存储空间安排在全局存储区,这样在下一次调用函数时还保留上一次对该变量的修改结果。
    当一个源程序由多个源文件组成时,用static修饰的全局变量和函数,其作用域为当前文件,对其他源文件不可见,即它们不能被其他源文件引用或调用。
    当函数的形参用const修饰时,在函数体内部不能被修改。

第 3 题

阅读以下说明和C函数,填补C函数中的空缺(1)~(6),将解答写在答题纸的对应栏内。
【说明】
函数numberOfwords(char message[])的功能是计算存储在message字符数组中的一段英文语句中的单词数目,输出每个单词(单词长度超过20时仅输出其前20个字母),并计算每个英文字母出现的次数(即频数),字母计数时不区分大小写。
假设英文语句中的单词合乎规范(此处不考虑单词的正确性),单词不缩写或省略,即不会出现类似don't形式的词,单词之后都为空格或标点符号。
函数中判定单词的规则是:
(1)一个英文字母串是单词;
(2)一个数字串是单词;
(3)表示名词所有格的撇号(')与对应的单词看作是一个单词。
除上述规则外,其他情况概不考虑。
例如,句子“The 1990's witnessed many changes in people's concepts of conservation.”中有10个单词,输出如下:
      The
      1990's
       witnessed
       many
       changes
       in
       people's
       concepts
       of
       conservation
函数numberOfwords中用到的部分标准库函数如下表所述。


【C函数】
       int numberOfwords (char message[])
       {
       char wordbuffer[21], i=0;    /* i用作wordbuffer的下标 */
                       (1)  pstr;
                      int ps[26]={0};    /* ps[0]用于表示字母'A'或'a'的频数 */
        /* ps[1]用于表示字母'B'或'b'的频数,依此类推 */
                      int wordcounter=0;
                     
                      pstr=message;
                      while (*pstr)  {
                               if( (2) (*pstr))  {/* 调用函数判定是否为一个单词的开头字符 */
                               i=0;
                               do{/* 将一个单词的字符逐个存入wordbuffer[],并进行字母计数 */
                                        wordbuffer[i++]=*pstr;
                                        if (isalpha (*pstr))  {
                                                  if( (3) (*pstr)) ps[*pstr-'a']++;
                                                  else  ps[*pstr-'A']++;
                                        }
                                         (4) ;    /* pstr指向下一字符 */
                               }while   (i<20 && (isalnum(*pstr)||*pstr=='\''));

if (i>=20)  /* 处理超长单词(含名词所有格形式) */
                while (isalnum (*pstr)||*pstr=='\'')  { pstr++; }
         
           (5) ='\0';    /* 设置暂存在wordbuffer中的单词结尾 */
wordcounter++;    /* 单词计数 */
                  puts (wordbuffer);    /* 输出单词 */
                  }
                    (6) ;    /* pstr指向下一字符 */
          }
          return wordcounter;
}

答案与解析

  • 试题难度:较难
  • 知识点:C程序设计>C程序设计
  • 试题答案:
    (1)char*,或unsigned char
    (2)isalnum,或isalpha(*pstr)||isdigit
    (3)islower,或!isupper
    (4)pstr++,或++pstr,或pst=str+1,或pstr+=1
    (5)wordbuffer[i],或*(wordbuffer+i)
    (6)pstr++,或++pstr,或pstr=pstr+1,或pstr+=1
  • 试题解析:
        本题考查C语言裎序设计基本技术。
        题目中涉及的知识点主要有字符串、字符指针和函数调用等,首先应认真阅读题目的说明部分,以了解函数代码的功能和大致的处理思路,然后理清代码的框架,明确各个变量(或数组元素)所起的作用,并以语句组分析各段代码的功能,从而完成空缺处的代码填充。
        函数中空(1)处所在语句为定义变量pstr的声明语句,根据下面对pstr的使用方式,可知pstr是一个指向字符的指针变量,因此空(1)处应填入“char*”。
        显然,“pstr=message;”使pstr指向了英文语句的第一个字符,下面的while循环则用于遍历语句中的每一个字符:
        while (*patr) {
        …
        }
        对于语句中的一个字符*pstr,它可能是一个单词中的字符、空格、标点符号或其他字符,由于函数的功能是取出单词并进行统计,因此首先考虑该字符是否属于一个单词以及是否是单词的开头(字母或数字字符),结合注释,可知空(2)处用于判定当前字符*pstr是否是单词的开头字符,即是否是字母或数字,由于代码中已给出了(*pstr),因此最合适的做法是直接调用库函数进行处理,即空(2)处应填入“isalnum”,也可以填入“isalpha(*pstr)||isdigit”。
        得到一个单词的开头字符后就用do-while语句依次取出该单词的每一个字符,直到单词结束为止。根据题目说明,单词中包含的字符为字母、数字或撇号('),因此do-while继续循环的条件之一是表达式“isalnum(*pstr)||*pstr-'\"”的值为“真”,另一个条件是关于单词长度不超过20的限制。
        分析空(3)所在的语句(如下所示),显然是对单词中的字母进行计数,在*pstr是字母(isalpha(*pstr)的返回值为1)的前提下,“ps[*pstr-'a']++”是对小写字母进行计数,“ps[*pstr-'A']++”是对大写字母进行计数,所以空(3)处应判断*pstr是否为小写字母,应填入“islower”,或者填入“!isupper”。
        if  (isalpha (*pstr)) {
                      if( (3) (*pstr)) ps[*pstr-'a']++;
                      else ps[*pstr-'A']++;
            }
        空(4)处是令pstr指向下一字符,因此应填入“pstr++”或其等价形式。
        空(5)处是设置字符串结尾字符,因此应填入“wordbuffer[i]”或其等价形式。
        空(6)处是令pstr指向下一字符,因此应填入“pstr++”或其等价形式。

第 4 题

阅读以下说明和C函数,填补C函数中的空缺(1)~(5),将解答写在答题纸的对应栏内。
【说明】
函数SetDiff(LA,LB)的功能是将LA与LB中的共有元素从LA中删除,使得LA中仅保留与LB不同的元素,而LB不变,LA和LB为含头结点的单链表的头指针。
例如,单链表LA、LB的示例如下图中的(a)、(b)所示,删除与LB共有的元素后的LA如下图中的(c)所示。

 
链表的结点类型定义如下:
   typedef struct Node {
       int data;
       struct Node *next;
   }Node, *LinkList;
函数SetDiff(LinkList LA, LinkList LB)的处理思路如下:
(1)从LA的第一个元素结点开始,令LA的第一个元素为当前元素。
(2)在LB中进行顺序查找,查找与LA的当前元素相同者,方法是令LA的当前元素先与LB的第一个元素进行比较,若相等,则结束在LB中的查找过程,否则继续与LB的下一个元素比较,重复以上过程,直到LB中的某一个元素与LA的当前元素相等(表明查找成功),或者到达LB的表尾(表明查找失败)为止。
(3)结束在LB表的一次查找后,若在LB中发现了与LA的当前元素相同者,则删除LA的当前元素,否则保留LA的当前元素。
(4)取LA的下一个元素为当前元素,重复(2)、(3),直到LA的表尾。

【C函数】
       void SetDiff (LinkList LA, LinkList LB)
       {
       LinkList pre, pa, pb;
       /* pa用于指向单链表LA的当前元素结点,pre指向pa所指元素的前驱 */
       /* pb用于指向单链表LB的元素结点 */
        (1) ;  /* 开始时令pa指向LA的第一个元素 */
       pre=LA;
       while (pa)  {
            pb=LB->next;
       /* 在LB中查找与LA的当前元素相同者,直到找到或者到达表尾 */
          while( (2) )  {
              if (pa->data==pb->data)
                 break;
                (3) ;
          }
         
          if (!pb)  {
          /* 若在LB中没有找到与LA中当前元素相同者,则继续考察LA的后续元素 */
                 pre=pa;
                 pa=pa->next;
             }
             else{
          /* 若在LB中找到与LA的当前元素相同者,则删除LA的当前元素 */
                 pre->next= (4) ;
                 free (pa);
                 pa= (5) ;
          }
}
}

答案与解析

  • 试题难度:较难
  • 知识点:C程序设计>C程序设计
  • 试题答案:
    (1)pa=LA->next
    (2)pb,或pb!=0,或pb!=NULL
    (3)pb=pb->next
    (4)pa->next
    (5)pre->next
  • 试题解析:
        本题考查C程序设计基本技术及指针的应用。
        题目中涉及的考点主要有链表的查找、删除运算以及程序逻辑,分析程序时首先要明确各个变量所起的作用,并按照语句组分析各段代码的功能,从而完成空缺处的代码填充。
        根据注释,空(1)处应为指针变量pa赋值,使其指向LA链表的第一个元素结点,由于LA为指向头结点的指针,因此空(1)处应填入“pa=LA->next”。
        以指针pa的值为循环条件的以下循环语句用于遍历LA的每一个元素。
        while (pa)  {
        …
        }
        对于LA中的每一个元素pa->data,需要在LB中查找是否存在与其相同者,代码段为:
        pb=LB->next;
        /* 在LB中查找与LA的当前元素相同者,直到找到或者到达表尾 */
          while( (2) )  {
            if (pa->data==pb->data)
              break;
             (3) ;
        }
        显然,通过“pb=LB->next”已经令pb指向了LB的第一个元素,接下来的while语句就用于和LB的元素pb->data逐个比较,显然,空(2)处应填入“pb”,表明pb为非空指针,使得循环体中进行“pa->data==pb->data”运算时,pb指针是有效的。在该循环中,若找到了两个链表的共有元素,则用break跳出循环,此时pb正指向LB中的该共有元素;否则继续在LB中查找,那就需要在空(3)处填入“pb=pb->next”。
        在LB结束查找后,如果找到了与pa->data相同的元素,则之前已经令pb指向它;若是没有找到,则pb是空指针。
        因此,接下来根据pb的值判断是否需要删除LA的当前元素。若不删除,则执行语句组“pre=pa; pa=pa->next;”,继续考察LA的后续元素;若需删除(pa指向的结点),则相关指针的指向如下图所示。
        
        显然,pre已经指向pa所指结点的前驱,要删除pa所指结点,只要将pre->next设置为指向pa所指结点的后继结点即可,即令pre->next= pa->next。因此,在free(pa)之后需重新设置pa的指向,即令pa= pre->next,为继续处理后续元素做好准备。对应地,空(4)应填入“pa->next”,空(5)应填入“pre->next”。

第 5 题

阅读以下说明和C++代码,填补C++代码中的空缺(1)~(6),将解答写在答题纸的对应栏内。
【说明】
已知某公司按周给员工发放工资,其工资系统需记录每名员工的员工号、姓名、工资等信息。其中一些员工是正式的,按年薪分周发放(每年按52周计算);另一些员工是计时工,以小时工资为基准,按每周工作小时数核算发放。
下面是实现该工资系统的C++代码,其中定义了四个类:工资系统类PayRoll,员工类Employee,正式工类Salaried和计时工类Hourly,Salaried和Hourly是Employee的子类。

【C++代码】
   //头文件和域名空间略
   const int EMPLOYEE_NUM=5;
   class Employee {
        protected:
              int empCode;            //员工号
              string name;            //员工姓名
              double salary;          //周发放工资
        public:
              Employee(const int empCode, const string &name ) {
                   this->empCode=empCode;    this->name=name;
              }
              virtual ~Employee(){ }
  virtual void pay()=0;
              double getSalary() { return this->salary; }
  };
  class Salaried  (1)  {
     private:     double payRate;    //年薪
     public:
       Salaried(const int empCode, const string &namet double payRate):Employee (empCode, name)   {
                     this->payRate=payRate;
       }
       void pay() {
           this->salary= (2) ;   //计算正式员工的周发放工资数
           cout << this->name << ":" << this->salary<<endl;
  };
  class Hourly  (3)  {
       private:
            double payRate;            //小时工资数
  int hours;                 //周工作小时数
     public:
         Hourly (const int empCode. const string &name, int hours, double payRate)
         :Employee(empCode, name) {
            this->payRate=payRate;    this->hours=hours;
     }
     void pay()  {
          this->salary= (4) ;  //计算计时工的周发放工资数
          cout << this->name << ":" << this->salary << endl;
     }
  };
  class PayRoll  {
     public:
         void pay (Employee*e[])  {
              for (int i=0;  i<EMPLOYEE_NUM; i++)  {
                   e[i]->pay();
             }
     }
};
int main()  {
     PayRoll payRoll=new PayRoll;
      (5)  employees [EMPLOYEE_NUM]= {
            new Salaried (1001, "Zhang San", 58000.00),
            //此处省略对其他职工对象的生成
            new Hourly (1005, "Li", 12, 50.00),
     };
     payRoll->pay( (6) );
     double total=0.0;
     for (int i=0;  i<EMPLOYEE_NUM; i++)
        { total+=employees[i]->getSalary();}    //统计周发放工资总额
        cout<<"总发放额="<<total<<endl;
        delete payRoll;  return 0;
}

答案与解析

  • 试题难度:较难
  • 知识点:C++程序设计>C++程序设计
  • 试题答案:
    (1):public Employee
    (2)payRate/52
    (3):public Employee
    (4)payRate*hours
    (5)Employee*或static Employee*
    (6)employees
  • 试题解析:
        本题考查C++语言程序设计能力,涉及类、对象、函数及虚函数的定义和相关操作,以及继承关系和多态。要求考生根据给出的案例和执行过程说明,认真阅读理清程序思路,然后完成题目。
        根据本题中说明中描述,需要记录每名员工的员工号、姓名和工资等信息。公司员工分为正式工和计时工两类,正式工和计时工的工资支付方式不同,根据面向对象设计的概念,这两种员工都是员工,设计时将公有属性和行为封装成抽象类,并使用继承关系设计两种不同员工类作为子类。因此,系统设计了4个类:工资系统类PayRoll、员工类Employee、正式工类Salaried和计时工类Hourly,Salaried和Hourly继承了Employee类。Employee中定义两类员工公有属性和方法,以及支付方式的接口标识,Salaried和Hourly需要在各自的类中有具体支付方式的实现。
        根据类定义及其之间的关系,将Employee类中支付工资定义为纯虚函数,即virtual void pay()=0;,这样就定义了支付方式的接口,子类中必须实现各自具体的支付方法。这样,在PayRoII中对Salaried和Hourly两类的对象使用同样的调用方式e[i]->pay()达到不同支付效果,也就达到了多态。Salaried和Hodrly均继承了Employee,并在Salaried和Hourly的构造函数中调用父类的构造函数,所以继承的权限为public,其语法为:public后加类名。Salaried的工资发放方式为“按年薪分周发放(每年按52周计算)”,因此在pay()方法的实现中,分周发放工资采用“年薪/52”进行计算。Hourly的工资发放方式是“以小时工资为基准,按每周工作小时数核算发放”,即“小时工资×周工作小时”进行计算。
        在main()中创建了一组员工,用数组存储,由于数组元素包括Salaried和Hourly两种,因此其声明类型采用父类类型Employee的指针,可以定义为静态数组,对蒙的创建采用new关键字加类名。集中对所有员工进行支付,将数据作为payRoll相同的pay()的参数,即payRoll->pay(employees)。用new关键字创建的数组,在使用完成之后通过delete进行释放。
        因此空(1)和(3)处添加继承父类,并且权限为public,即:public Employee。空(2)和(4)处补充通过使用计算得到所发放的工资额,空(2)处为计算正式员工的周发放工资数,即payRate/52;空(4)处为计时工的周发放工资数,即payRate*hours。空(5)处定义员工数组的类型,即Employee*或static Employee*。空(6)处将员工数组传递给pay()方法,即employees。

第 6 题

阅读以下说明和Java代码,填补Java代码中的空缺(1)~(6),将解答写在答题纸的对应栏内。
【说明】
已知某公司按周给员工发放工资,其工资系统需记录每名员工的员工号、姓名、工资等信息。其中一些员工是正式的,按年薪分周发放(每年按52周计算);另一些员工是计时工,以小时工资为基准,按每周工作小时数核算发放。
下面是实现该工资系统的Java代码,其中定义了四个类:工资系统类PayRoll,员工类Employee,正式工类Salaried和计时工类Hourly,Salaried和Hourly是Employee的子类。

【Java代码】
abstract class Employee  {
   protected String name;    //员工姓名
   protected int empCode;    //员工号
   protected double salary;    //周发放工资
   public Employee(int empCode, String name)  {
       this.empCode=empCode;
       this.name=name,
   }
   public double getSalary(){
       return this.salary;
   }
public abstract void pay() ;
}

class Salaried  (1)  Employee  {
   private double annualSalary;
   Salaried(int empCode, String name, double payRate) {
       super(empCode, name) ;
       this.annualSalary=payRate;
   }
   public void pay () {
       salary= (2) ;    //计算正式员工的周发放工资数
       System.out.println(this.name+":"+this.salary);
   }
}

class Hourly  (3)  Employee  {
   private double hourlyPayRate;
   private int hours;
   Hourly(int empCode, String name, int hours, double payRate) {
       super(empCode, name);
       this.hourlyPayRate=payRate;
       this.hours=hours;
   }
   public void pay () {
       salary= (4) ;    //计算计时工的周发放工资数
       System.out.println(thisname+":"+this.salary);
   }
}

public class PayRoll  {
   private  (5)  employees[]={
       new  Salaried(1001, "Zhang San", 58000.00),
//此处省略对其他职工对象的生成
       new Hourly(1005, "Li", 12, 50.00)
   };
   public void pay(Employee e[])  {
       for (int i=0; i<e.length; i++)  {
           e[i]pay();
       }
   }
   public static void main(String[] args)
   {
       PayRoll payRoll=new PayRoll();
       payRoll.pay( (6) );
       double total=0.0;
       for (int i=0;i<payRoll.employees.length; i++){             //统计周发放工资总额
              total+=payRoll.employees[i].getSalary();
       }
System.out.println(total);
   }
}

答案与解析

  • 试题难度:较难
  • 知识点:Java程序设计>Java程序设计案例
  • 试题答案:
    (1)extends
    (2)annualSalary/52
    (3)extends
    (4)hourlyPayRate * hours
    (5)Employee 或 static Employee
    (6)employees(空(5)只能为static Employee)或payRoll.employees
  • 试题解析:
        本题考查Java语言程序设计能力,涉及类和抽象类、对象、方法及抽象方法的定义和相关操作,以及继承关系和多态。要求考生根据给出的案例和执行过程说明,认真阅读理清程序思路,然后完成题目。
        根据本题中说明中描述,需要记录每名员工的员工号、姓名和工资等信息。公司员工分为正式工和计时工两类,正式工和计时工的工资支付方式不同,根据面向对象设计的概念,这两种员工都是员工,设计时将公有属性和行为封装成抽象类,并使用继承关系设计两种不同员工类作为子类。因此,系统设计了四个类:工资系统类PayRoll,员工类Employee,正式工类Salaried和计时工类Hourly,Salaried和Hourly继承了Employee类。Employee中定义两类员工公有属性和方法,以及支付方式的接口标识,Salaried和Hourly需要在各自的类中有具体支付方式的实现。
        根据类定义及其之间的关系,将Employee类定义为抽象类,其中支付工资定义为抽象方法,public abstract void pay();,这样就定义了支付方式的接口,子类中必须实现各自具体的支付方法。这样,在PayRoll中对Salaried和Hourly两类的对象使用同样的调用方式e[i].pay()达到不同支付效果,也就达到了多态。Salaried和Hourly均继承了Employee,其语法为extends后加类名,在两者的构造方法中调用父类的构造方法,进行相应的员工公共信息初始化操作,所以均在构造方法的第一句(必须是第一句)采用super调用父类构造方法。Salaried的工资发放方式为“按年薪分周发放(每年按52周计算)”,因此在pay()方法的实现中,每周发放工资采用“年薪/52”进行计算。Hourly的工资发放方式是“以小时工资为基准,按每周工作小时数核算发放”,即“小时工资×周工作小时”进行计算。
        在PayRoII中创建了一组员工,用数组存储,由于数组元素包括Salaried和Hourly两种,因此其声明类型采用父类类型Employee,可以定义为静态数组,对象的创建采用new关键字加类名。在PayRoll中支付时,集中对所有负工进行支付,将数据作为payRoll的pay()的参数,在Java中用数组引用名直接作为参数,即payRoll.pay(payRoll.employees)。
        因此空(1)和(3)处添加继承父类,即extends。空(2)和(4)处补充通过使用计算得到所发放的工资数,空(2)处为计算正式员工的周发放工资数,即annuaISalary/52;空(4)处为计时工的周发放工资数,即hourlyPayRate*hours。空(5)处定义员工数组的类型,即Employee或static Employee。空(6)处将员工数组的引用传递给pay()方法,即employees(空(5)只能为static Employee)或payRoll.employees。

results matching ""

    No results matching ""