1. 程式人生 > >C++語言學習(三)——封裝(Encapsulation)

C++語言學習(三)——封裝(Encapsulation)

++ pro sta 模板 參數 函數 擴展 init 類屬性

C++語言學習(三)——封裝(Encapsulation)

一、封裝簡介

C語言等面向過程編程中,數據以及數據的相關操作函數都是分離的獨立個體;在C++等面向對象編程中,數據以及數據的相關操作被設計為對象,對象包括屬性(數據)和操作(函數),兩者共同構成對象實體(即類實體)。面向對象編程使程序更模塊化,更易讀易寫,提升了代碼重用到一個更高的層次。
面向對象編程中,數據和數據的操作封裝為了對象。封裝可以隱藏實現細節,使得代碼模塊化,是把過程和數據包圍起來,對數據的訪問只能通過已定義的接口。
封裝是一種對外提供服務的模型,封裝模型是對世間萬物的個體抽象。
封裝的訪問屬性如下:
訪問屬性 屬性 對象內部 對象外部

public 公有 可訪問 可訪問
protected 保護 可訪問 不可訪問
private 私有 可訪問 不可訪問
C語言中,struct中所有行為和屬性都是public的(默認),既可以使用接口,又可以直接訪問其內部數據,沒有屏蔽內部數據。
C++語言中,強化了C語言的封裝特性,struct、class可以指定行為和屬性的訪問方式,對內開放數據,對外屏蔽數據,對外提供接口。

二、C語言的封裝

C語言中,通常使用模塊化進行封裝。
stack的C語言實現:

#include <stdio.h>
#include <string.h>

typedef struct stack
{
    char space[1024];
    int top;
}stack;

void stack_init(stack *st)
{
    st->top = 0;
    memset(&st->space, 0, sizeof(st->space));
}

int is_empty(stack *st)
{
    return st->top == 0;
}
int is_full(stack *st)
{
    return st->top == 1024;
}

char pop(stack *st)
{
    return st->space[--st->top];
}

void push(stack *st, char c)
{
    st->space[st->top++] = c;
}

int main(void)
{
    stack st;
    stack_init(&st);
    unsigned int i;
    for(i = ‘a‘; i < (‘z‘ + 1); i++)
    {
        if(!is_full(&st))
            push(&st, i);
    }
    for(i = ‘a‘; i < (‘z‘ + 1); i++)
    {
        printf("%c\n", pop(&st));
    }
    return 0;
}

C語言中封裝的struct的數據成員是可以被外部調用修改的。

三、C++語言的封裝

1、C++語言的封裝

C++語言強化了C語言的封裝,在類的表示法中定義了屬性和行為的訪問級別。
C++語言中,用於表示類屬性的變量為成員變量;用於表示類行為的函數為成員函數。C++語言中,可以對類的成員變量和成員函數定義訪問級別。
public:使用public關鍵字聲明的類的成員變量和成員函數可以在類的內部和外部訪問與調用
private:使用private關鍵字聲明的類的成員變量和成員函數只能在類的內部訪問和調用
protected:使用protected關鍵字聲明的類的成員變量和成員函數只能在本類以及派生子類的內部訪問和調用。

類的成員的作用域只在類的內部,外部不能直接訪問。類的成員函數可以直接訪問成員變量和調用成員函數。類的外部可以通過類對象訪問public成員。
C++語言中,struct定義的類中成員的默認訪問權限為public,class定義的類中成員的默認訪問權限為private。

2、C++語言的struct

C++語言中,對struct關鍵字進行了擴展,struct已經不只是C語言中變量集合的struct,C++語言中的struct不僅可以定義成員函數,也可以實現繼承和多態。與C語言中的struct一樣,C++語言中使用struct定義類時,成員的默認訪問級別為public。

#include <iostream>

using namespace std;

struct Person
{
    const char* name;
    int age;
    virtual void print()
    {
        printf("My name is %s, I‘m is %d years old.\n",name,age);
    }
};
//默認繼承訪問權限為public
struct Student : Person
{
    void print()
    {
        printf("My name is %s, I‘m is %d years old."
               "My score is %d\n",name,age,score);
    }
    void setScore(const int n)
    {
        score = n;
    }
private:
    int score;
};

int main(int argc, char *argv[])
{
    Person p;
    p.name = "Bob";
    p.age = 30;
    p.print();
    Student s;
    s.name = "Bauer";
    s.age = 20;
    s.setScore(98);
    s.print();
    dynamic_cast<Person*>(&s)->print();
    return 0;
}

3、C++語言的class

由於C++語言的struct需要兼容C語言的struct,C++語言使用新的class關鍵字定義類。使用class定義類時,成員的默認訪問級別為private。
C++中的類支持聲明和實現的分離,將類的定義和實現分開,通常.h頭文件中只有類的聲明,包括成員變量和成員函數的聲明;.cpp源文件中完成類的成員函數的實現。

#include <iostream>

using namespace std;

class Person
{
public:
    const char* name;
    int age;
    virtual void print()
    {
        printf("My name is %s, I‘m is %d years old.\n",name,age);
    }
};

class Student : public Person
{
public:
    void print()
    {
        printf("My name is %s, I‘m is %d years old."
               "My score is %d\n",name,age,score);
    }
    void setScore(const int n)
    {
        score = n;
    }
private:
    int score;
};

int main(int argc, char *argv[])
{
    Person p;
    p.name = "Bob";
    p.age = 30;
    p.print();
    Student s;
    s.name = "Bauer";
    s.age = 20;
    s.setScore(98);
    s.print();
    dynamic_cast<Person*>(&s)->print();
    return 0;
}

4、C++語言struct與class的區別

C++語言中struct與class最本質的區別如下:
A、默認訪問權限不同。struct默認的訪問權限是public的,class默認的訪問權限是private的。
B、默認繼承訪問權限不同。struct默認的繼承訪問權限是public的,class默認的繼承訪問權限是private的。
C、class可用作定義模板參數的關鍵字,而struct不可以。
C++語言中,繼承時如果沒有指定繼承訪問權限,默認繼承訪問權限是public繼承還是private繼承,取決於子類而不是基類。struct可以繼承class,class也可以繼承struct,默認的繼承訪問權限取決於子類是struct還是class,如果子類使用struct聲明,默認繼承訪問權限是public;如果子類使用class聲明,默認繼承訪問權限是private。

#include <iostream>

using namespace std;

class Person
{
public:
    const char* name;
    int age;
    virtual void print()
    {
        printf("My name is %s, I‘m is %d years old.\n",name,age);
    }
};
//默認繼承訪問權限為public
struct Student : public Person
{
public:
    void print()
    {
        printf("My name is %s, I‘m is %d years old."
               "My score is %d\n",name,age,score);
    }
    void setScore(const int n)
    {
        score = n;
    }
private:
    int score;
};

int main(int argc, char *argv[])
{
    Person p;
    p.name = "Bob";
    p.age = 30;
    p.print();
    Student s;
    s.name = "Bauer";
    s.age = 20;
    s.setScore(98);
    s.print();
    dynamic_cast<Person*>(&s)->print();
    return 0;
}

5、C++語言封裝示例

C++類實現stack:
stack.h源碼:

#ifndef STACK_H
#define STACK_H

class stack
{
public:
    stack();
    bool is_empty();
    bool is_full();
    void push(char c);
    char pop();
private:
    char space[1024];
    unsigned int top;
};

#endif // STACK_H

stack.cpp源碼:

#include "stack.h"
#include <string.h>

stack::stack()
{
    top = 0;
    memset(space, 0, sizeof(space));
}

bool stack::is_empty()
{
    return top == 0;
}

bool stack::is_full()
{
    return top == 1024;
}

void stack::push(char c)
{
    space[top++] = c;
}

char stack::pop()
{
    return space[--top];
}

main.cpp源碼:

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

int main()
{
    stack st;
    unsigned int i;
    for(i = ‘a‘; i < ‘z‘ + 1; i++)
    {
        if(!st.is_full())
            st.push(i);
    }
    for(i = ‘a‘; i < ‘z‘ + 1; i++)
    {
        cout<<st.pop()<<endl;
    }
    return 0;
}

C++語言中封裝的class stack中數據成員是private的,對於外部不可訪問,通過設置數據成員和操作方法的訪問權限,可以對外部開放、屏蔽數據成員和操作方法。C++通過定義類成員的訪問級別實現封裝機制。C++語言中類支持聲明和實現的分離,在頭文件中聲明類,在源文件中實現類。

C++語言學習(三)——封裝(Encapsulation)