代码改变世界

白话C++系列(8)-- 数据封装

2016-04-11 21:11  Keiven_LY  阅读(1243)  评论(0编辑  收藏  举报

属性封装的艺术

数据的封装

下面看一个例子,例子中定义了一个学生的类,类中含有两个数据成员,一个是姓名,一个是年龄

上面的代码给人一种相当亲切,有一种似曾相识的感觉,那是因为之前我们一直都是这么用的,而且用的也很爽。但是,这样用是有问题的,最大的问题是它违背了面向对象的指导思想。

那么面向对象的基本思想是什么呢?

面向对象的核心就是以对象为中心,具体来说,就是要以谁做什么来表达程序的逻辑,体现在代码层面上,就是将所有的数据操作转换为成员函数的调用。换句话说,对象在程序中的所有行为都通过调用自己的函数来完成。

那么如何通过函数来封装数据成员呢?

接着继续看上面这个例子,这次我们把数据成员定义在private的下面,以年龄这个数据成员为例,我们定义两个成员函数,一个用于设置年龄的值,一个用于读取年龄的值

封装的好处

以上面Student的类为例,当我们还是用以前的老方法来访问数据成员,如果赋值时出现非法的情况,比如,给年龄数据成员赋值1000,显然是有问题的。但是如果通过数据的封装,就能很好的解决这个问题。

还是以上面Student的类为例,上面的封装只是简单的封装,如果我们对上面的成员函数setAge()做一下改变(如下),就会避免了上面非法输入的问题了。

接着以汽车(Car)为例来进一步说明封装的好处,如下

我们定义一个Car类,在这个类下面定义了一个private属性的数据成员,表示汽车轮子的个数,针对这个数据成员,我们不希望外界通过某个函数来改变它的值,我们只希望能读取它的值就ok了。我们称这种只能读取而不能设置的属性为只读属性

代码实践

题目描述:

定义一个Student类,含有如下信息:

1 姓名:name

2 性别:gender

3 学分(只读):score

4 学习:study(用于获得学分)

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;

/*   **********数据的封装
定义一个Student类,含有如下信息:
1 姓名:name
2 性别:gender
3 学分(只读):score
4 学习:study(用于获得学分)
/*  ************************************/

class Student
{
public:
    void setName(string _name)
    { 
        m_strName = _name;
    }
    string getName()
    {
        return m_strName;
    }
    void setGender(string _gender)
    { 
        m_strGender = _gender;
    }
    string getGender()
    {
        return m_strGender;
    }
    int getScore()
    {
        return m_iScore;
    }
    void initScore()
    {
        m_iScore = 0;
    }
    void study(int _score)
    {
        m_iScore += _score;
    }
private:
    string m_strName;
    string m_strGender;
    int m_iScore;
};

int main()
{
    Student stu;
    stu.initScore();//如果这里不进行初始化,m_iScore的值就不可控
    stu.setName("Zhangsan");
    stu.setGender("");
    stu.study(5);//学习一门学分为5分的课程
    stu.study(3);//学习一门学分为3分的课程

    cout<<stu.getName() <<" "<<stu.getGender() <<" "<<stu.getScore() <<endl;

    system("pause");
    return 0;
}

运行结果: