C++特性一:封装

作者:jicanmeng

时间:2014年08月12日


封装(encapsulation)是面向对象程序设计语言的第一个特性,是通过类(class)来实现的。为了说明什么是封装,先看一个程序。

#include <iostream>
using namespace std;

class C2DPoint
{
private:
    int m_xPos;
    int m_yPos;
public:
    void setAxis(int x, int y) {
        m_xPos = x;
        m_yPos = y;
    }
    int getXAxis() {
        return m_xPos;
    }
    int getYAxis() {
        return m_yPos;
    }
};

int main()
{
    C2DPoint ptA;

    ptA.setAxis(5, 6);
    cout << "point axis is (" << ptA.getXAxis() <<
        ", " << ptA.getYAxis() << ")" << endl;

    return 0;
}

编译此文件并运行,看一看运行结果:

[jicanmeng@andy tmp]$ g++ test.cpp
            [jicanmeng@andy tmp]$ ./a.out
            point axis is (5, 6)
            [jicanmeng@andy tmp]$

封装是通过类(class)来实现的。一个类中包含了数据和操作这些数据的函数。所谓的封装,就是将数据和操作数据的函数封装在一起。我们先看一个使用类的c++程序。

在c++中,声明一个类的一般格式如下:

class <类名>	//声明部分
{
private:
    [<私有型数据和函数>]
public:
    [<公有型数据和函数>]
protected:
    [<保护型数据和函数>]
};
<各个成员函数的实现> //实现部分

其中,class是类声明的关键字,class后面是要声明的类名。类中的数据和函数都是类的成员,分别称为类的数据成员(variable member)和函数成员(function member)。对于函数成员,有的书或教程也称其为成员函数(member function)。但是我觉得,无论是变量还是函数,都是类的成员。为了保持一致,后面统一称为变量成员和函数成员。其中数据成员又称为类的属性,函数成员又称为类的方法。在定义一个类时,要注意类体中最后一个花括号后面的分号";"不能省略。

在c++语言中,常常将类定义的变量称为一个对象,对象的数据成员称为这个对象的属性,对象的函数成员称为这个对象的方法。

类体中的关键字public,private和protected声明了类中的成员和类外代码的关系,称为访问权限(access specifiers)。对于public类型的成员来说,可以在类外访问,当然也可以在类内访问。对于private成员来说,不能在类外访问,数据成员只能由类中的函数使用,函数成员只允许在类中调用。对于protected成员来说,不能在类外访问,只能在类中或子类中访问。

从类的声明格式可以看出,类的声明分为声明部分和定义部分。通常情况下,我们会将类的声明部分放到一个头文件中,实现部分放到一个cpp文件中。一般情况下,各个函数成员的实现都是放在cpp文件中的。不过,我们也可以将函数成员的实现直接放到类体中,比如上面的示例程序。

如果函数成员的实现是在类体外部完成,那么必须使用作用域运算符"::"来告知编译系统该函数所属的类。此时,函数成员的定义格式如下:

<函数类型> <类名>::<函数名>(<形参表>)
{
	……
}

我们再修改一下上面的程序:

#include <iostream>
using namespace std;

class C2DPoint
{
private:
    int m_xPos;
    int m_yPos;
public:
    void setAxis(int x, int y) {
        m_xPos = x;
        m_yPos = y;
    }
    int getXAxis();
    int getYAxis();
};

void C2DPoint::getXAxis()
{
    return m_xPos;
}

void C2DPoint::getYAxis()
{
    return m_yPos;
}

int main()
{
    C2DPoint ptA;

    ptA.setAxis(5, 6);
    cout << "point axis is (" << ptA.getXAxis() <<
        ", " << ptA.getYAxis() << ")" << endl;

    return 0;
}

几点说明:

  1. 类中的数据成员的数据类型可以是任意的,如整型,字符型,指针类型,class类型等
  2. 由于类是一种数据类型,系统并不会为其分配内存空间,所以在定义类的数据成员时,不能对其初始化,也不能指定除static之外的任何存储类型。
  3. In order to use a class, a variable of that class type must be declared.
  4. 访问权限关键字public,private和protected在类中使用时先后次序无关紧要,而且可以使用多次。每个访问权限关键字为类成员确定的访问权限是从该关键字开始到下一个关键字为止。另外要注意的是,这三个关键字表示的是类的成员与类外的关系,类内部成员之间互相访问不受这三个关键字的限制。
  5. 类体内如果没有指定成员的访问权限,则默认为private的。
  6. 在类外,对某个对象的数据成员的访问方式为:"对象名.数据成员名称";对某个对象的函数成员的访问方式为:"对象名.函数成员名称(形参表)"。
  7. 在类中使用成员时,成员声明的前后不会影响该成员在类中的使用。
  8. 声明一个class类型的变量时,我们称为实例化这个类。这个变量称为类的一个实例,一个class类型的变量常常称为一个对象。
  9. 类的数据成员和函数成员在命名时,加上"m_"前缀比较好,表示member of class的意思。这样容易和类外部定义的变量和函数区分。
  10. 在实际编程时,我们往往将类的声明放在一个.h头文件中,将类的具体实现放在.cpp文件中。

参考资料

  1. C++实用教程 电子工业出版社 郑阿奇,丁有和编著
  2. The C++ Tutorial:
    http://www.learncpp.com/cpp-tutorial/82-classes-and-class-members/