48. 类中的封装

类的组合

  • 学习电脑组装需要多少时间?

  • 学习电脑组装是否需要学习显示器,键盘,鼠标,主板,内存等部件的设计与制造?不需要,封装

类通常分为以下两个部分

  • 类的实现细节

  • 类的使用方式

当使用类时,不需要关心其实现细节;当创建一个类时,才需要考虑其内部实现细节

例:

  • 使用手机时(使用类),只需要知道如何发短信,打电话,拍照等等即可,不需要关心手机是如何开发出来的。

  • 手机开发工程师(创建类)就需要考虑手机内部的实现细节,如硬件细节和软件细节。

类的封装

封装的基本概念

  • 根据日常生活中的经验:并不是类的每个属性都是对外公开的

    • 如:女孩子不希望外人知道自己的年龄和身高

    • 如:一些男孩子不希望别人知道自己会尿床

  • 而一些类的属性是对外公开的

    • 如:人类的姓名,学历,国籍等

  • 因此,需要在类的表示法中定义属性和行为的公开级别

    • 类似文件系统中文件的权限

C++中类的封装

  • 成员变量

    • C++中用于表示类属性的变量

  • 成员函数

    • C++中用于表示类行为的函数

  • 在C++中可以给成员变量和成员函数定义访问级别

    • public

      • 成员变量和成员函数可以在类的内部和外界访问和调用

    • private

      • 成员变量和成员函数只能在类的内部被访问和调用

类成员的访问属性

#include <stdio.h>

struct Biology 
{
    bool living;
};

struct Animal : Biology 
{
    bool movable;
    void findFood() 
    { 
    }
};

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

struct Girl : Human
{
private:
    int age;//只能在类的内部被访问和调用

public:
    void play()
    {
        printf("I'm girl, I'm playing...\n");
    }
    
    void print()
    {
        age = 22;
        
        printf("Girl's age is %d\n", age);
         
        play();
        sleep();
        work();
    }
};

struct Boy : Human
{
public:
    int age;
    
    void play()
    {
        printf("I'm boy, I'm playing...\n");
    }
    
    void print()
    {
        age = 23;
        
        printf("Boy's age is %d\n", age);
        
        play();
        sleep();
        work();
    }
};

int main(int argc, char *argv[])
{
    Girl girl;
    girl.print();

    Boy boy;
    
    boy.print();
    
    printf("Press any key to continue...");
    getchar();
    return 0;
}
result:
Girl's age is 22
I'm girl, I'm playing...
I'm sleeping...
I'm working...
Boy's age is 23
I'm boy, I'm playing...
I'm sleeping...
I'm working...
Press any key to continue...

类成员的作用域

类成员的作用域都只在类的内部,外部无法直接访问

  • 成员函数可以直接访问成员变量和调用其它成员函数

类的外部可以通过类变量访问public成员

  • 类成员(成员函数、成员变量)的作用域与访问级别没有关系??

  • 一个类成员的作用域总是限制在类的内部,但访问级别决定了这个成员在类外部的可访问性。

C++中用struct定义的类的所有成员默认为public

类成员的作用域

#include <stdio.h>

int i = 1;

struct Test
{
private:
    int i;//作用域Test,访问权限private

public:
    int j;
        
    int getI()
    {
        i = 3;
        
        return i;
    }
};

int main()
{
    //在main函数里定义的局部变量i,它的作用域覆盖了全局变量i的作用域
    int i = 2;
    
    Test test;
    
    test.j = 4;
    
    printf("i = %d\n", i);
    printf("::i = %d\n", ::i);//::i访问默认命名空间里的i,int i = 1;
    //printf("test.i = %d\n", test.i);//private,类外无法访问
    printf("test.j = %d\n", test.j);
    printf("test.getI() = %d\n", test.getI());
    
    printf("Press any key to continue...");
    getchar();
    
    return 0;
}
result:
i = 2
::i = 1
test.j = 4
test.getI() = 3
Press any key to continue...

类的真正形态

struct在C语言中已经有了自己的含义,只能继续兼容

在C++中提供了新的关键字class用于类定义

class和struct的用法是完全相同的

  • 在用struct定义类时,所有成员的默认属性为public

  • 在用class定义类时,所有成员的默认属性为private

一个运算类的实现★

要求:

  • 提供setOperator函数设置运算类型,如加,减,乘,除

  • 提供setParameter函数设置运算参数,类型为整型

  • 提供result函数进行运算,其返回值表示运算的合法性,通过引用参数返回结果

Operator.h

#ifndef _OPERATOR_H_
#define _OPERATOR_H_

class Operator
{
private:
    char mOp;
    double mP1;
    double mP2;
    
public:
    bool setOperator(char op);
    void setParameter(double p1, double p2);
    bool result(double& r);
};

#endif

Operator.cpp

#include "Operator.h"

bool Operator::setOperator(char op)
{
    bool ret = false;
        
    if( (op == '+') || (op == '-') || (op == '*') || (op == '/') )
    {
        ret = true;
        mOp = op;
    }
    else
    {
        mOp = '\0';
    }
        
    return ret;
}

void Operator::setParameter(double p1, double p2)
{
    mP1 = p1;
    mP2 = p2;
}
    
bool Operator::result(double& r)
{
    bool ret = true;
        
    switch( mOp )
    {
        case '/':
            if( (-0.000000001 < mP2) && (mP2 < 0.000000001) )
            {
                ret = false;
            }
            else
            {
                r = mP1 / mP2;
            }
            break;
        case '+':
            r = mP1 + mP2;
            break;
        case '*':
            r = mP1 * mP2;
            break;
        case '-':
            r = mP1 - mP2;
            break;
        default:
            ret = false;
            break;
    }
        
    return ret;
}

main.cpp

#include <stdio.h>
#include "Operator.h"

int main(int argc, char *argv[])
{
    Operator op;
    double r = 0;
    
    op.setOperator('/');
    op.setParameter(8, 4);
    
    if( op.result(r) )
    {
        printf("Result is %f\n", r);
    }
    
    printf("Press any key to continue...");
    getchar();
    return 0;
}

g++ main.cpp Operator.cpp -o myprogram

.\myprogram.exe

Result is 2.000000
Press any key to continue...

运算类的改进👆

在Operator中所有成员函数的实现都在类中完成

  • 问题:对于使main函数来说,只需要知道怎么使用Operator即可,没有必要知道其实现

  • 解决方案:将Operator类的实现和定义分开

    • Operator.h头文件中只有类的声明

    • Operator.cpp中完成类的其它实现

小结

类的精华在于封装

将实现细节和使用方式相分离

C++中通过public和private实现类的封装

public成员可以通过变量被外界访问

private成员只能够在类内部使用

类的定义和实现可以分开到不同的文件中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值