对数据类型封装和数据抽象的简单理解
2014-11-15 23:04
337 查看
请特别关注程序设计技术,而不是各种语言特征。
--《C++程序设计语言》 Bjarne Stroustrup
本文是《C++程序设计语言》(Bjarne Stroustrup )的第二章的读书笔记,例子来源于这本书的第二章。
在程序设计之中,我们倾向于将数据结构(也可以说是数据类型)以及一组对其操作的相关过程组织在一起,在逻辑上可以称将其为模块。此时程序分为一些模块,模块包括一组对数据的操作,数据隐藏于模块之中。以下以栈的设计为例,使用C和C++进行设计,简单理解模块化设计中的数据封装和数据抽象。
对于C 语言我们可以对栈这一数据类型进行如下简单的设计:
由于struct结构可以自由的有外界进行访问,因此可能对数据进行破坏。我们可以引入类似于win32编程使用到的句柄的设计。即:
只有在实现该数据类型相关的操作,才知道Stack的内在结构,可以进行强制到转换。因此该模块的用户无需知道struct Stack的结构,改变struct Stack结构也不会影响到API用户的使用。
客户端代码:
因此C语言在进行类似的数据类型封装时,通常提供的一组操作中通常包含了初始化和回收的操作,通常需要用户有意识的进行调用。这让这一数据类型有点“伪类型”的感觉,C语言的特征无法让封装的数据类型进行自动的初始化和销毁。
C++提供类这一用户自定义类型对数据类型封装进行支持。在进行程序设计时,通过确定需要哪些类型,为每个类型提供完整的操作。对栈的定义如下:
构造函数Stack(int) 在建立这个类的对象时被调用,处理初始化问题。如果该类的一个对象出了其作用域,进行某些清理的时候,通过调用其析构函数。
像上面的Stack这种类型的定义,我们可以称为就具体类型,涉及到具体的实现。在类型不常改变,或者类型用于局部变量的情况下,这种设计方法足够解决问题。在一些情况下我们希望有抽象类型。抽象类型可以将用户与实现细节隔离,得到更好的灵活性。此时用户面向抽象类型编程,而不是面向具体类型编程。 C++可以通过类的继承和抽象类实现这一方式。如:
通过定义Stack这一抽象类(在C++中可以理解为具有纯虚成员函数的类。 如:virtual void push(int) = 0;),为这一抽象类提供不同实现获得灵活性,用户面向这一抽象类编程(在C++中,通常是该类型对象的引用或者指针,才能实现多态)。
--《C++程序设计语言》 Bjarne Stroustrup
本文是《C++程序设计语言》(Bjarne Stroustrup )的第二章的读书笔记,例子来源于这本书的第二章。
在程序设计之中,我们倾向于将数据结构(也可以说是数据类型)以及一组对其操作的相关过程组织在一起,在逻辑上可以称将其为模块。此时程序分为一些模块,模块包括一组对数据的操作,数据隐藏于模块之中。以下以栈的设计为例,使用C和C++进行设计,简单理解模块化设计中的数据封装和数据抽象。
对于C 语言我们可以对栈这一数据类型进行如下简单的设计:
typedef struct Stack { int elem[MAX_SIZE]; int top; } Stack; Stack* createStack(); void destroyStack(Stack*); void push(Stack*,int); int pop(Stack*);
由于struct结构可以自由的有外界进行访问,因此可能对数据进行破坏。我们可以引入类似于win32编程使用到的句柄的设计。即:
typedef void* HStack; HStack createStack(); void destroyStack(HStack hStack); void push(HStack hStatck,int) { struct Stack* stack = (struct Stack*)hStack; ........ } int pop(HStack hStack) { struct Stack* stack = (struct Stack*)hStack; ........ }
只有在实现该数据类型相关的操作,才知道Stack的内在结构,可以进行强制到转换。因此该模块的用户无需知道struct Stack的结构,改变struct Stack结构也不会影响到API用户的使用。
客户端代码:
void f() { HStack h= createStack(); push(h,2); int i = pop(h); destroyStack(h); }
因此C语言在进行类似的数据类型封装时,通常提供的一组操作中通常包含了初始化和回收的操作,通常需要用户有意识的进行调用。这让这一数据类型有点“伪类型”的感觉,C语言的特征无法让封装的数据类型进行自动的初始化和销毁。
C++提供类这一用户自定义类型对数据类型封装进行支持。在进行程序设计时,通过确定需要哪些类型,为每个类型提供完整的操作。对栈的定义如下:
class Stack { public: Stack(int max_size); ~Stack(); void push(int); int push(); private: int* m_elem; int m_top; int m_max_size; };
构造函数Stack(int) 在建立这个类的对象时被调用,处理初始化问题。如果该类的一个对象出了其作用域,进行某些清理的时候,通过调用其析构函数。
像上面的Stack这种类型的定义,我们可以称为就具体类型,涉及到具体的实现。在类型不常改变,或者类型用于局部变量的情况下,这种设计方法足够解决问题。在一些情况下我们希望有抽象类型。抽象类型可以将用户与实现细节隔离,得到更好的灵活性。此时用户面向抽象类型编程,而不是面向具体类型编程。 C++可以通过类的继承和抽象类实现这一方式。如:
class Stack { public: virtual void push(int) = 0; virtual int pop(int) = 0; }; // 使用数组实现栈 class ArrayStack : public Stack {}; // 使用链表实现栈 class ListStack : public Stack{}; // 用户面向抽象类编程: void f(Stack& s) { s.push(2); int i = s.pop(); }
通过定义Stack这一抽象类(在C++中可以理解为具有纯虚成员函数的类。 如:virtual void push(int) = 0;),为这一抽象类提供不同实现获得灵活性,用户面向这一抽象类编程(在C++中,通常是该类型对象的引用或者指针,才能实现多态)。
相关文章推荐
- java中八种基本数据类型以及它们的封装类,String类型的一些理解
- 不可变数据类型的简单理解
- Java数据类型转换(简单类型、封装类型、String)
- java中八种基本数据类型以及它们的封装类,String类型的一些理解
- C++简单学习(Part2_lecture 9)(数据抽象、数据封装、接口(抽象类))
- 对final数据类型的简单理解
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- oc加强day5-NSFileManger、NSPoint与CGPoint等简单结构体、简单数据类型的封装、集合对象的内存管理、copy、单列模式
- 数据基本类型,符合数据类型,数据结构的理解,抽象数据结构
- java:关于short s1=1;s1=s1+1;short s1=1;s1+=1;short s3=s1+s2;中存在的简单数据类型转换问题的理解
- oracle表的管理,数据类型简单理解
- java获取redis中各种数据类型key对应的value代码简单封装
- java获取redis中各种数据类型key对应的value代码简单封装
- 第二章、2.简单数据类型转换和类封装
- 深入理解C#:从简单的数据类型开始
- java:关于short s1=1;s1=s1+1;short s1=1;s1+=1;short s3=s1+s2;中存在的简单数据类型转换问题的理解
- java中八种基本数据类型以及它们的封装类,String类型的一些理解
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- 对C#数据类型的简单理解(value与ref区别、ref与out区别)
- 1.java的八种基本数据类型以及其封装类的理解应用