Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2358854
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类:

2010-06-29 14:48:05

下面是一份我从csdn上下载的四维计算机公司的上机试题. 该试题本身附有一份参考答案, 出处不明. 下面是我对这份参考答案的分析. 借此可以让多年以后的我可以比较一下自己当年的编程观有什么不同.
=================== 题目说明 ==========

C++ Test

 

Suggest that every candidate creates a “Win32 Console Application” project (or any other project that they feel comfortable with) and the folder created by VC++ (maybe named as the candidate’s name ?) should be returned here (they can even use notepad if they don’t like VC++, but the studio will help them debug/compile the problem). We only need the files with the class/functions requested (we expect one .h and one .cpp file) if too difficult for you to select then send the entire folder

 

Visual C++ 2008 Express Edition can be installed from here if required:

 

 

1.      Write a C++ class (Employee) that has name (string) and weight (int) as protected data members. The name can be of any length.

Implement the following methods in the class: constructor (takes a name and a weight as parameters), destructor, GetName (returns the name), GetWeight (returns the weight) and a virtual method GetType that returns the type of object (employee in this case).

 

2.      Add a second class named Manager, inherited from Employee that has the same constructor as Employee and also overrides the method GetType to return the new object type: manager.

 

3.      In a global function add the following objects to an array of void pointers of size 10:

-          type employee: name Matt, weight 89

-          type employee: name John, weight 79

-          type employee: name Andy, weight 59

-          type manager: name Nick, weight 65

-          type employee: name Chris, weight 86

-          type employee: name Rob, weight 75

-          type manager: name Conrad, weight 83

-          type manager: name David, weight 110

-          type employee: name Richard, weight 63

-          type manager: name Paul, weight 95

 

4.      Implement a function called Sort that sorts the array given above by the object type (managers first) and then by weight (ascending) if the type is the same.

 

 

 

General observations:

-          no external/API functions should be used (like string, use char* instead of any library versions of string)

-          it is not necessary to output/format the results, these can be seen by running the program in debug mode

-          help documentation can be used

-          if point 2 is too difficult then marks will be given for point 4 even if the sorting is done only by  weight using same type objects in the array

-          besides functionality, marks will be given for the style of coding and the tidiness of the code

======================  题目说明 < ======================

======================  test.h ======================
// 评: {从可移植的角度看, #pragma once 不如 include guard, 但注意include guard不要使用
// _开头和含有两个下划线的标识符, 此类标识符为标准所保留.}
#pragma once

// PART 1 of the test
// 评: {题意中没有说明应该返回的employee 的数据类型, 使用枚举中规中矩}
enum EmployeeType { eEmployee, eManager };

class CEmployee
{
// 评: {题意中明确说要把这两个标识符定义为protected访问级别, 窃以为应该是private, 使用尽低
//      且可以工作的访问级别}
protected:
    char* m_strName;
    int m_nWeight;

public:
// 评: {此处API设计不好, strName完全可以为const char *, 参考strcpy类函数. nNameLen是
//      将负担强加给API的使用者 }
    CEmployee(char* strName, int nNameLen, int nWeight);
// 评: {此处为最大的硬伤, 该类为基类, dtor应为virtual }
    ~CEmployee();

// 评: {此处API设计不好, 返回char *使用者不能仅从函数原型及说明知道返回的内存资源owner为谁,
//      是否由caller负责释放, 是否可写, 如果caller意外地改写了返回值指向的内存, 下次返回的
//      值就不对了.
//      最好通过const 指定该函数是 const 的(注意不是指返回值)  }
    char* GetName() { return m_strName; }
    int GetWeight() { return m_nWeight; }

    virtual EmployeeType GetType() { return eEmployee; }
};


// PART 2 of the test
class CManager: public CEmployee
{
public:
    CManager(char* strName, int nNameLen, int nWeight) :
      CEmployee(strName, nNameLen, nWeight) {}

    EmployeeType GetType() { return eManager; }
    // 评: {参考上面的dtor设计硬伤, 此处应该有一个dtor, 虽然无用. 这导致向CManager中添加
    //      新的需要动态分配和释放的资源很困难. }
};

void MyTest();
======================  test.h <> ======================

======================  test.cpp ======================
#include "Tester.h"

// PART 1 of the test
// 评: {对参数 strName, nNameLen, nWeight的合法性未做检查, 也没有错误处理机制 }
CEmployee::CEmployee(char* strName, int nNameLen, int nWeight)
{
    m_strName = new char[nNameLen + 1];
    for (int i = 0; i < nNameLen; i++)
    {
        m_strName[i] = strName[i];
    }
    m_strName[nNameLen] = 0;

    m_nWeight = nWeight;
}

CEmployee::~CEmployee()
{
    // 评: {赞, 虽然看似是常识, 不是每个人都会对new[] 使用 delete[]的 }
    delete []m_strName;
}

// PART 4 of the test
// 评: { 1: main中将CEmployee或CManager的指针统一保存为 void *, 并将这些void *放在
//       一个数组中, 将该数组通过参数传递到此, 该函数中, 再通过强制类型转换得到相应
//       的CEmployee指针, 因为main中存在 CManager * => void *的转换, 而这里统一使用
//       void * => CEmployee的逆转换. 这在典型的Windows上或Linux环境上都是运行时正确的,
//       因为所有这些指针类型的大小都一样. 但却不是严格安全的可移植的做法. 标准只保证任何指针
//       可以转换到void *, 再转换回来时恢复原值, 不保证跨类型的转换是安全的.
//       2. 到处使用10 这样的magic number, 要严重减分, API的典型设计, 在指针后面紧跟着的
//          参数中, 用size_t 类型表示指针所指向的元素的个数(而不是字节数)
//       3. }
void Sort(void** arr)
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = i + 1; j < 10; j++)
        {
            // 评: { 最好使用C++风格的cast }
            CEmployee* left = (CEmployee*)arr[i];
            CEmployee* right = (CEmployee*)arr[j];
           
            bool swap = false;
            if (left->GetType() < right->GetType())
            {
                swap = true;
            }
            else if (left->GetType() == right->GetType())
            {
                if (left->GetWeight() > right->GetWeight())
                {
                    swap = true;
                }
            }

            if (swap)
            {
                CEmployee* tmp = left;
                arr[i] = right;
                arr[j] = tmp;
            }
        }
    }
}

// PART 3 & 4 of the test
void MyTest()
{
    // 评: { 10的所有出现, 都可以消除, 此处可以使用不指定长度的数组, 在定义的同时指定
    //       初始化值. 如 int ia[] = { 1, 2, 3}; 其数组元素数个自然为3, 后面可以使用
    //       _countof(MSVC only)中 sizeof(a)/sizeof(a[0]) 得到数组长度 }
    void* per[10];

    per[0] = new CEmployee("Matt", 4, 89);
    per[1] = new CEmployee("John", 4, 79);
    per[2] = new CEmployee("Andy", 4, 59);
    per[3] = new CManager("Nick", 4, 65);
    per[4] = new CEmployee("Chris", 5, 86);
    per[5] = new CEmployee("Rob", 3, 75);
    per[6] = new CManager("Conrad", 6, 83);
    per[7] = new CManager("David", 5, 110);
    per[8] = new CEmployee("Richard", 7, 63);
    per[9] = new CManager("Paul", 4, 95);

    Sort(per);

    for (int i = 0; i < 10; i++)
    {
        delete (CEmployee*)per[i];
    }
}
======================  test.cpp <> ======================
阅读(1330) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~