类和封装的概念

本文参照于狄泰软件学院《C++深度剖析》

什么是类?

我们知道电脑一般而言是由CPU,内存,主板,键盘和硬盘等部件组合而成。那么我们如何用程序代码像组装电脑一样,吧各个部分分开开来,又可以相互组合呢?

类的封装

我们可以把程序按某种规则分成很多“块”,类与类之间可能会有联系,每个类都有一个可变部分(public)和一个不可变部分(private)。我们需要把可变部分和不可变部分分离出来,将不可变的部分暴露给其他类,而将可变的部分隐藏起来,以便于随时可以让它修改。这项工作就是封装。

类分为以下两个部分
- 类的实现细节
- 类的使用方式

类为什么需要封装?

  1. 当使用类时,不需要关心其实现细节。当我们创建类时,才需要考虑其内部实现细节。

    例如:普通用户使用手机,只需要学习如何发短信,打电话,拍照等等。而这些功能如何实现,则是手机开发工程师需要考虑的事情。

  2. 高内聚,低耦合移植时我们所追求的,用好封装恰恰可以减少耦合

  3. 只要对外接口不改变,可以任意修改内部实现,这个可以很好的应对变化。
  4. 类具有了简洁清晰的对外接口,降低使用者的学习过程。

如何将一个类封装?

1. 根据经验:并不是类的每个属性都是对外公开的(私有)
如:女孩子不希望外人知道自己的体重和年龄
如:男孩子不希望别人知道自己的身高和收入

2. 而一些类的属性是对外公开的(公有)
如:人的姓名,学历,国籍等

3. 必须在类的表示法中定义属性和行为的公开级别
类似文件系统中文件的权限

C++中类的封装


  1. 成员变量:C++中用于表示类属性的变量
  2. 成员函数:C++中用于表示类行为的函数
  3. C++中可以给成员变量和成员函数定义访问级别

根据访问级别的不同,设定不同的访问权限。
- public
成员变量和成员函数可以在类的内部和外界访问和调用
- private
成员变量和成员函数只能在类的内部被访问和调用
示例代码:类成员的访问属性

struct Human
{
    void sleep()
    {
        printf("I'm sleeping...\n");
    }

    void work()
    {
        printf("I'm working...\n");
    }
};

struct Girl : Human
{
private:
    int age;
    int weight;
public:
    void print()
    {
        age = 22;
        weight = 48;

        printf("I'm a girl, I'm %d years old.\n", age);
        printf("My weight is %d kg.\n", weight);
    }
};

struct Boy : Human
{
private:
    int height;
    int salary;
public:
    int age;
    int weight;

    void print()
    {
        height = 175;
        salary = 9000;

        printf("I'm a boy, my height is %d cm.\n", height);
        printf("My salary is %d RMB.\n", salary);
    }   
};

int main()
{
    Girl girl;
    Boy boy;
    Human human;

    human.sleep();

    girl.print();

    boy.age = 19;
    boy.weight = 120;
    boy.height = 180; //Error: ‘int Boy::height’ is private

    boy.print();

    boy.work();

    return 0;
}

分析:
1. 从我们通过boy.height = 180;修改boy对象中的身高的值时,编译时会产生错误。提示我们Boy::height这个成员变量是私有的。但是我们却可以在boy.printf()函数中修改height的值。所以我们可以知道:private的成员只能在类的内部被访问和调用
2. 我们通过boy.age = 19;编译时并没有发生错误可以知道。类的public成员可以在类的外部修改,所以public的成员可以在类的内部和外界访问和调用
3. 我们在Human这个类中没有明显定义类的成员属于private还是属于public,但是我们在main中调用它编译没有报错。说明struct定义的类默认为public的。
4. 我们可以在boy中使用Human类中的函数work();

类成员的作用域

我们知道全局变量和局部变量都有作用域,那么类也有作用域吗?

示例代码:类成员的作用域

#include <stdio.h>

int i = 1;

struct Test
{
private:
    int i;

public:
    int j;

    int getI()
    {
        i = 3;

        return i;
    }
};

int main()
{
    int i = 2;

    Test test;

    test.j = 4;

    printf("i = %d\n", i);              // i = 2;
    printf("::i = %d\n", ::i);          // ::i = 1;
    // printf("test.i = %d\n", test.i);    // Error
    printf("test.j = %d\n", test.j);    // test.j = 4
    printf("test.getI() = %d\n", test.getI());  // test.getI() = 3

    return 0;
}

分析:
1. 我们单纯打印printf(“i = %d\n”, i); i的变量是main函数内定义的i的值,而不是全局变量i=4的值。这是因为小范围作用域的值会覆盖大范围作用域的值。
2. 我们使用::作用域解析运算符来使用默认全局变量i的值。
3. 我们访问Test类中成员时,不能从外部直接访问类的成员,公有成员变量和成员函数也是不能直接访问,需要通过对象才能访问类的成员。如代码所示:访问类成员i变量,需要定义一个test对象,通过test对象才能访问i的值。
4. 类成员的作用域都只在类的内部,外部无法直接访问。也就是说不同类中使用相同的类成员名不会发生冲突。实际上类与命名空间有点相像。

猜你喜欢

转载自blog.csdn.net/small_prince_/article/details/80008153