- 论坛徽章:
- 0
|
陈良乔 发表于 2012-04-23 16:07
6.4.43 实现类的属性和行为
完成上面的分析与设计之后,小陈深深地伸了个懒腰。他知道,只要完成了程序中 ...
看了你的代码,提出一些意见:
// 枚举员工的级别
typedef enum _EmpLevel
{
enumOfficer = 1, // 高级员工
enumStaff = 2 // 一般员工
}EmpLevel ;后面会将其最为参数类型使用,所以建议用typedef定义 // 员工类
class Employee --------a、这里类名不是CXXXX,说明不是匈牙利命名法
{
public:
// 构造函数,根据员工的姓名和入职年份构造对象
Employee(const string strName, const int nY) ---------b、这里的年份使用了n作为前缀,说明是匈牙利命名法,前后不一;只读入参用const修饰
:m_strName(strName),m_nYear(nY) // 设定员工的姓名和入职年份
{}
// Employee类的行为,这些行为都是供外界调用的,
// 所以将其访问级别设定为public
public:
// 获得员工姓名
string GetName() const ----GET方法使用const修饰,保证成员变量不被修改,是个好习惯
{
return m_strName;
}
// 获得员工入职年份
int GetYear() const
{
return m_nYear;
}
// 获得员工级别
EmpLevel GetLevel() const
{
return m_nLevel;
}
// 获得员工工资,因为这个行为同具体的员工类相关,
// 不同的派生类有不同的行为(计算方法),所以在基类Employee中只是
// 用纯虚函数表示接口,具体内容由其派生类实现
virtual int GetSalary() = 0;
// Employee类的属性
// 因为这些属性也同样应当是其派生类具有的,需要由基类遗传给
// 它的派生类,所以这里使用protected访问控制,允许其派生类继承这些属性
protected:
string m_strName; // 姓名
int m_nYear; // 入职年份
EmpLevel m_nLevel; // 级别 ---------枚举为什么用n前缀
}; // 对数组进行初始化
for(long i = 0; i<MAX; ++i) ---------虽然很多时候int跟long占用空间是一样的,但是此处还是建议i使用int类型,因为MAX就是int,保持一致最好
{
m_arrEmp = NULL;
} int Read()
{
// 用于文件读取的中间变量
string strName = ""; -------这三个循环体内的局部变量为什么这么突兀的放在这里
int nLevel = 0;
int nYear = 0;
// 读取的数据个数
int i = 0; ----------这种语句看起来不难受吗
// 打开数据文件
ifstream in(m_strFileName);
if( enumOfficer == nLevel)
{
// 根据员工姓名和入职年份,创建高级员工对象
m_arrEmp = new Officer(strName,nYear);
}
else if ( enumStaff == nLevel) -----------使用else。很多静态检查工具认为有else if没有else的条件判断语句是不完备的,很有可能是作者这对条件判断的处理不齐备
{
m_arrEmp = new Staff(strName,nYear);
} Employee* GetMax()
{
// 表示结果的指针,初始值为NULL
Employee* pMax = NULL;
// 设定一个假想的当前最大值
int nMax = INT_MIN;
// 用for循环遍历数组中的每一个对象
for(int i = 0;i < m_nCount; ++i)
{
// 如果当前对象的工资高于当前最大值nMax,则将当前最大值
// 替换为当前对象的工资,并将当前对象的指针作为结果保存
// 这里使用的是基类Employeed 的指针,调用基类的公有接口函数 // GetSalry()。但是因为这个接口函数是虚函数,所以实际上,它们
// 将调用这个指针所指向的实际对象的相应函数。例如,这里通过指针
// pMax对GetSalary() 函数的调用,编译器将根据pMax这个基类
// 指针所指向的具体对象是Office还是Staff来决定到底是调用
// Officer类中的GetSalary()实现还是Staff类中的GetSalary()
// 实现。这就是面向对象中多态的体现——基类的指针,调用的却是
// 它所指向的具体派生类对象的函数。 ---------注释太多,导致代码可读性反而下降
if(m_arrEmp->GetSalary()>nMax)
{
// 则将当前对象记录为结果对象
pMax = m_arrEmp;
// 并将当前对象的工资记录为当前最大值
nMax = pMax->GetSalary();
}
}
// 返回指向拥有最高工资的员工对象的指针
return pMax;
} // 构造无限循环进行查询 ------无用注释
while(true)
{ // 记录是否找到查询的员工
bool bFind = false; -----标志变量,看着真难受
int _tmain(int argc, TCHAR* argv[]) ----------定义为C++的书籍,怎么会出现这个玩意。这就像一本操作系统原理的书里面,都是讲windows原理一样
{
没有看代码逻辑是否正确,只看了代码本身,个人意见如下:
1、关于继承和多态的讲述是正确的
2、感觉作者缺乏实际工程经验
3、注释太多,好的代码要做到自注释。作者这样写的话会给初学者注释越多代码越好的错误印象,如果非要进行解释,因为将代码拆分,
再在文本中解释,而不是直接贴一大片代码并使用注释阐明作者需要讲解的意图。
4、写代码还不够严谨,没有“推敲”的态度
5、函数的实现都放到了类的定义里面,这是为了把函数定义成inline吗?那几个Get函数肯定是可以的,但是其他的函数里面有大量的处理,
尤其有循环,编译器会否认inline属性的,所以这样做完全是主观臆断,初学者会被误导。
6、措辞轻松是好,但是太不严肃了点,不过这个见仁见智了。
|
|