C语言面向对象编程学习笔记

2024-07-09

C语言面向对象编程学习笔记(精选7篇)

篇1:C语言面向对象编程学习笔记

C语言面向对象编程笔记

1、在底层驱动函数前加static标识符的作用:

a:加了static后表示该函数失去了全局可见性,只在该函数所在的文件作用域内可见 b:当函数声明为static以后,编译器在该目标编译单元内只含有该函数的入口地址,没有函数名,其它编译单元便不能通过该函数名来调用该函数,这也是对1的解析与说明

2、底层驱动的封装模板

通常将存储类,显示类,AD-DA类的外设驱动函数封装为以下几个函数: Void Open(void);

此函数用于开启外设,通常函数体中包涵IO和外设的初始化 Void Close(void)此函数用于关闭外设,特别是一些在休眠下功耗很大的外设,可用mos管控制其Vcc的通断,以此达到降低系统功耗的目的

Void Read(unsigned int address,unsigned char *data[],unsigned int count)

此函数用于读取数据,参数分别为:address,地址,*data[],存放数据的数组,count,要读取的字节数

Void Write(unsigned int address,unsigned char *data[],unsigned int count)此函数用于写数据,参数功能与读函数中相似。

Void control(unsigned char cmd,unsigned char data)此函数用于控制外设的工作状态,如休眠,低功耗等等

3、命名规则

A、宏定义全部用大写

如:#define OLED_CS PBout(12)B、驱动函数名称大小写,并且动词放置在末尾如

static long _OLED_Close(void)C、结构体的名称,结构体名大写,变量名小写,“驱动”的首字母大写

如:struct OLED_DEVICE oledDevice;

4、关于外设的数据手册

外设的数据手册应该去芯片的官网下载最新版本,特别注意芯片的是否有功耗控制方面的内容,

篇2:C语言面向对象编程学习笔记

其实 Lua 中的 table 是一种对象,因为它跟对象一样,有其自己的操作方法:

代码如下:

Role = { hp = 100 }

function Role.addHp(hp)

Role.hp = Role.hp + hp

end

Role.addHp(50)

print(Role.hp)

上面代码创建了一个名为 Role 对象,并有一个 addHp 的方法,执行 “Role.addHp” 便可调用 addHp 方法,

不过上面对象 Role 是以全局变量的方式创建,会有一种“全局污染”的威胁,即变量 Role 在其他地方被重新赋值(例如被赋成 nil),对象里的属性或方法可能会面临被销毁或不能正常工作的情况。

对于这种问题,Lua 提供一种“接受者”的解决方法,即额外添加一个参数 self 来表示对象本身:

代码如下:

Role = { hp = 100 }

function Role.addHP(self, hp)

self.hp = self.hp + hp

end

r = Role

r.addHP(r, 50)

print(r.hp)

这样就不怕对象 Role 被“全局污染”,因为构造了一个子对象 r,并以参数的方式传入,以供其方法调用操作。

对于这种把对象本身以参数的方式传入对象方法里的写法,Lua 提供了一种更优雅的写法,把点号(.)替换为冒号(:),这样在方法定义或调用时,便可隐藏 self 参数。修改如下:

代码如下:

Role = { hp = 100 }

function Role:addHp(hp)

self.hp = self.hp + hp

end

r = Role

r:addHp(50)

print(r.hp)

上面的 “r.addHp(50)” 的写法等价于 “r.addHp(r, 50)”

Lua 没有类的概念,不过可以通过元表(metatable)来实现与原型 prototype 类似的功能,而 prototype 与类的工作机制一样,都是定义了特定对象行为。Lua 里的原型特性主要使用元表的 __index 事件来实现,这样当调用对象没定义的方法时,会向其元表的 __index 键(事件)查找。例如有 a 和 b 两个对象,想让 b 作为 a 的原型 prototype,只需要把 b 设置为 a 元表的 __index 值就行:

代码如下:

setmetatable(a, {__index = b})

这样,当对象 a 调用任何不存在的成员都会到对象 b 中查找,a 可以拥有或调用 b 的属性或方法,从某种意义上看,b 可以看作是一个类,a 是 b 的对象。

对于上面 Role 的例子,对象的创建可以用 __index 元方法来改写,这样新创建的对象就拥有和 Role 一样的属性和方法。

代码如下:

function Role:new(o)

o = o or {}

setmetatable(o, self)

self.__index = self

return o

end

当执行 “r = Role:new ” 创建一个对象时,r 将 Role 设置为自己的元表,那么调用 “r:addHp(50)” 的时候,会在 r 里查找 addHp 方法,如果没有找到,则会进一步搜索其元表的 __index,因此等价于:

代码如下:

getmetatable(r).__index.addHp(r, 50)

从上面的 Role:new 方法可以知道,Role 的 __index 在创建时被指定为 self,因此其实就是执行:

代码如下:

Role.addHp(R, 50)

完整的类例子:

代码如下:

Role = { hp = 100 }

function Role:new(o)

o = o or {}

setmetatable(o, self)

self.__index = self

return o

end

function Role:addHp(hp)

self.hp = self.hp + hp

end

r = Role:new()

r:addHp(50)

print(r.hp)

继承

Lua 里继承机制还是像实现类那样实现,

假如打算从类 Role 派生出一个子类 Priest,它有一个魔法属性值 mp,那么可以先从类 Role 构造一个 Priest,继承类 Role 的所有属性和方法:

代码如下:

Priest = Role:new()

虽然 Priest 是 Role 的一个实例,不过它具有类 Role 的所有属性和方法,其实也可以把它看做是从类 Role 派生出来的类,因此可以从类 Priest 继续 new 一个对象出来:

代码如下:

p = Priest:new({ mp = 100 })

上面实例 p 除了多出一个魔法属性值 mp 外,还继承类 Role 的所有属性和方法,当调用 “p.addHp” 方法时,Lua 在 p 中找不到 addHp 方法,会到 Priest 中找,在 Priest 中找不到,会到 Role 中找。

因此,想重定义从父类 Role 继承来的方法,在类 Priest 上定义即可。假如想重定义 addHp 方法:每次加血都要先判断魔法值够不够,如果够,则加血,并扣除一定的魔法值。修改如下:

代码如下:

function Priest:addHp(hp)

if self.mp >= 20 then

self.mp = self.mp - 20

self.hp = self.hp + hp

end

end

篇3:基于汇编语言的面向对象编程

汇编语言编程的优点是速度快, 可以直接对硬件进行操作, 能够直接访问与硬件相关的存储器或 I/O 端口, 最大限度地发挥硬件的功能, 它可以不受编译器的限制, 对生成的二进制代码进行完全的控制, 能够对关键代码进行更准确的控制, 避免因线程共同访问或者硬件设备共享引起死锁, 可以根据特定的应用对代码做最佳的优化, 提高运行速度。在嵌入式系统、对硬件控制要求较多或对系统性能要求比较严格的场合, 应用汇编语言往往收效较好。

面向对象技术可以让用户实现抽象的数据类型, 通过继承大幅度地降低了代码重用现象, 提高了程序的开发效率。许多高级编程语言 (如c++、Java、Delphi等) 都支持面向对象技术, 但是由于这些高级编程语言最终都要将它们的源代码翻译成底层的机器代码, 所以在高级编程语言中支持的类和对象等概念, 在汇编语言中也应该存在对应的实现方法。但是大多数汇编语言的汇编器并没有为编写面向对象程序提供很好的支持, 而高级汇编语言HLA (High Level Assembly) 却为编写面向对象的汇编程序提供了很好的支持, 提高了代码的重用性, 为实现抽象数据类型提供了一种好的方法, 同时也提高了汇编程序的开发效率。

1HLA中的面向对象描述

1.1类

从本质上说, 类是一个允许定义非数据域 (如过程、常量和宏等) 的记录声明, 但在类的定义中包含其它的对象, 使类的功能大大超过了记录。在HLA中创建抽象数据类型的基本方法是声明一个类数据类型, 类的声明部分可以定义const、val、var和static等变量, 它总是出现在Type部分, 并使用以下语法:

Classname:class

<<class declaration section >>

Endclass;

在类中定义的所有过程、迭代器和方法都必须在后面的代码中有真正的实现, 可以选择把@external选项附在类中过程、迭代器和方法声明的结尾处, 用来告诉HLA真正的代码将出现在一个单独的模块中。作为一条通用规则, 类声明一般出现在头文件中, 用来表示抽象数据类型 (abstract data type, ADT) 的接口部分。过程、迭代器和方法体均出现在实现部分, 通常是一个单独的源文件, 可以单独编译, 并且能链接到使用该类的模块上。

类过程的声明和标准过程的声明是有区别的, 首先, 过程名包含了类名, 但需要注意的是在过程的begin和end子句中, 并不一定要在过程名前重复类名;另外, 一些过程属性 (如@use、@external、@retruns、@cdecl、@stdcall和@pascal等) 只在类的原型声明中才是合法的, 而另一些属性 (如@noframe、@nodisplay、@noalignstack和@align等) 则只在过程定义中才是合法的。

如果一个类例程的原型没有@external选项, 那么包含类声明的编译单元必须还包含这个例程的定义, 否则, HLA将在编译的结尾产生一个错误。一般情况下, 局部类会把类的过程、迭代器和方法的定义放在紧跟类声明之后的源文件中, 而当单独编译一个类的模块时, 一般将类的声明单独放在一个头文件中, 而将所有的过程、迭代器和方法的定义放在一个独立的HLA单元中, 并且对其进行单独编译。

1.2对象

类只是定义了一种类型, 在声明类之后还没有创建可以操作它的域的变量。对象是类的实例, 即一个类的变量, 可以像声明其它变量一样在var、static或storage段中声明对象。HLA为类声明中的每一个出现在var部分中的变量分配存储单元。

静态数据对象在类的对象中不是惟一的, HLA只分配一个静态变量, 而类的所有变量共享该静态变量。例如, 在以下的类和对象声明中, var3.var1和var4.var1是两个不同的变量, 而var3.var2和var4.var2却互为别名。

通常用静态变量保存有关整个类的信息, 而用类的var对象保存有关指定对象的信息, 也可以创建类的动态实例并通过指针指向那些动态对象。

1.3继承、重载和方法

继承是一个类从其它类中复制所有的域, 且可以在新的数据类型中扩展域的数目。重载是用一个更适合新类的方法替代继承类中现有方法的过程。

HLA是通过一个指向对象的指针来调用方法, 而不是直接通过对象变量来调用方法, 在通常情况下, 当程序通过指针间接引用数据时, 指针的值是与指针相关联的底层数据类型的某些值的地址。同样, 指向某些记录的指针不能正常指向其它的记录类型, 也不能访问其它类型的域, 但是使用指向类对象的指针可以降低该限制, 指向对象的指针可以包含该类型对象的地址, 或者任何继承了该类型的域的对象地址。如果已经获得了一个指向某个对象的指针, 并且调用了一个与该对象相关联的方法, 系统将会调用和对象相关联的被重载的方法, 而不是那个只与指针类型相关联的方法。当通过对象指针间接调用类的过程时, 系统将始终调用与基类相关联的过程。

2HLA中的面向对象实现

2.1编写类方法和过程

对于类定义中的每一个类过程和方法原型, 都必须有一个相应的过程体或方法体, 如果原型没有包含@external选项, 那么这些代码就必须和类的声明出现在同一个编译单元中, 如果原型后面跟着@external选项, 那么代码可以和类的声明出现在同一个编译单元中, 也可以出现在不同的编译单元中, 只要将最后所得到的对象文件和包含类声明的代码链接在一起就行。和外部过程一样, 如果没有提供代码, 则构建可执行文件时, 链接程序就会报错。

在一个编译单元中, HLA类例程必须始终紧跟在类的声明之后, 如果在单独一个单元中编译例程, 那么类的声明仍然必须置于例程的实现之前, 通常是通过#include文件来实现。如果直到定义一个例程时还没有定义类, 那么HLA就不知道如何处理例程的定义。

HLA在调用一个类例程时, 会自动将一个指针传递给一个对象的数据域, HLA在ESI寄存器中传递这个对象的指针, 将对象的地址自动加载到ESI寄存器中。对于类的方法, HLA也会将类的虚拟方法表 (virtual method table) 的地址加载到EDI寄存器中, 但当调用类方法或迭代器时, 由HLA产生的代码将重写EDI中的值。在类例程的入口, ESI包含了一个指向与类相关联的数据域的指针, 因为ESI作为对象数据域的基址, 所以最好不要改变类例程中的值。

2.2实现对象

汇编语言编程可以完全领会底层的实现细节, 允许在底层随意操作数据结构, 有助于创建可靠的算法, 但如果没有对象实现的详细知识, 就不会做到这些。

HLA用一种与记录非常类似的方式实现对象, 用与记录一样的连续方式为类中所用的var对象分配存储单元。类和记录的实现之间的区别在于类对象的开头部分多了一个虚拟方法表VMT (virtual method table) 指针域, 它包含了类的VMT的地址, VMT的地址依次包含了所有类的方法和迭代器的地址, 即使一个类不含任何方法或迭代器, 但必须有VMT域。HLA不会自动产生VMT, 必须在程序中显式第声明该表, 声明时只要在程序的static或readonly段中包含如下语句即可:

Readonly

VMT (classname) ;

当HLA调用类过程时, 和任何普通过程调用一样, 直接用一个调用指令调用该类过程即可。系统中的每个对象都将一个指针传送到VMT中, VMT是一个指向类中所有方法和迭代器的指针数组, 如图1所示。

在类中声明的每一个方法或迭代器在VMT中都有一个相应的入口, 该入口包含了方法或迭代器中的首条指令的地址, 所有类都会将指向VMT的指针放在对象中偏移量为0的地址, 在程序中有一个单独的VMT和每一个类相关联, VMT就是一个指向类相关的方法或迭代器的指针数组。出现在类中的第一个方法或迭代器的地址在偏移量为0 位置, 第二个在偏移量为4的位置, 依次类推。子类继承基类中的域时, 子类的VMT都会从基类的VMT中继承入口。如下为一个典型的调用序列:

Mov (objectadress, esi) ;

Mov ([esi], edi) ;

Call ( (type dword [edi+n]) ) ;

其中第一条指令将类对象的地址装入ESI寄存器, 第二条指令将VMT的地址装入EDI寄存器, 第三条指令调用一个放或迭代器, 其中的n是要调用方法或迭代器在VMT中的偏移量。

虽然VMT在一个对象中总是出现在偏移量为0的地方, 但是HLA实际上是将一个符号插入到符号表中, 所以只能

2.3初始化对象

在使用一个对象之前, 要确保已为该对象初始化了虚拟方法表的指针, 假设有以下的对象声明:

Var

Var1:tBaseclass;

……

Var1:mbase () ;

在对该对象的VMT地址初始化的一种简单的方式为:

Mov (&tBaseclass._VMT_, var1._pVMT_) ;

每个特定的类都可能有它自己的具体应用需要初始化, 虽然初始化可能根据类的不同而不同, 但是需要对每个特定的类的对象进行同样的初始化。如果曾经从一个给定的类中创建了多个对象, 则可以在创建的过程中进行初始化工作。

利用上面定义的类和对象就可以构造抽象的数据类型, 从而在汇编语言程序设计过程中实现了面向对象的编程思想和方法。

3总结

通过上面介绍的方法, 可以在汇编语言中实现面向对象编程技术, 从而可以编写出时间上和空间上比高级语言效率更高的程序。

参考文献

[1]Irvine K R.Assembly language for intel-based Computers (fourth edition) .北京:清华大学出版社, 2005

[2]Hyde R.The art of assembly language.北京:清华大学出版社, 2005

[3]严义, 包键, 周尉.Win32汇编语言程序设计教程.北京:机械工业出版社, 2005

[4]罗云彬.Windows环境下32位汇编语言程序设计.北京:电子工业出版社, 2002

[5]张长海, 郭东伟, 左万历, 等.Pentium汇编语言程序设计.北京:高等教育出版社, 2005

篇4:C语言面向对象编程学习笔记

关键词:VB.NET;面向对象编程;排课系统设计

中图分类号:TP311文献标识码:A文章编号:1007-9599 (2013) 06-0000-02

1引言

排课问题是一所学校的教学及其他活动的基准。我国的高等教育事业的不断发展,通常情况下,各大高校将分配到本校的计算机排课系统提交到院校的教务部,由负责的数据工作人员录入电脑。这种最基本的排课系统,只能在一定程度上提高效率。因此,计算机系统研究人员也在不断探索更先进的计算机技术,从而使教务人员从复杂的任务中解放出来,提高老师的教学备课时间有效地利用教学资源,而且还提高教学管理的质量和教育管理的工作效率。如何减少教务工作者的工作强度,更有效地利用人力和物力资源,如何管理和利用好数据信息,已经成为当前人们关注的主要问题。

VB就是Visual Basic 的简称,它是一种可视化编程语言,功能包括应用程序、编写代码以及用户界面设计。Visual Basic6.0中改变程序的机制,是对传统意义上的主程序的改造,它是通过子程序驱动。作为面向对象编程语言,代码和数据相结合,大大提高了程序设计的效率,当前程序员只需要编写传统上程序员函数代码中的一部分。用户在使用时,也大大简化,只需知道程序的功能,至于它是如何工作的就不必知道了。

2编程语言Visual Basic.NET概述

开发数据库系统的首选语言是Visual Basic.NET,通常被简称为VB.NET,是基于NET框架的面向对象的编程语言。VB.NET是可以用来创建多种程序的编程机制,包括Windows应用程序、网络服务和网络程序、智能设备等,并且支持面向对象。

Visual Basic.NET和现在所知的开发工具完全不同,Visual Basic.NET具有强大的网络功能。其一是VB.NET中有它将是DCOM的取代者;其二是VB.NET中还有Web Forms,它代表了一个一个的Web页面。它的特点包括,作用广泛,容易掌握,使用也十分方面,拥有支持可视化继承的窗口板块设计器,程序采用标准化界面,真正支持面向对象和继承性。

3排课系统需求分析

3.1用户需求分析

班级信息有所在教室、所在教室上课班级的个数、班级学委的联系方式、班级专业编号;课程信息有班级专业编号、每学期总课时数目、每周节数以及是否分单双周上课、任课教师基本信息;教师信息包括手机号或其他联系方式、教师所上课程名称等;时间信息包括所上课程是第几周、第几节以及是否需要临时补课等。每门课程都有自己的期末考核办法,可以是书面作业,也可以是社会实践;每门课程可以规定禁止安排上课时间,也可以指定教师。

每个教室属于一个教学区域、教室名称、教室类型。为了考虑节约教学资源,根据教学班人数来安排合适容量的教室。同时,在同一时间每个教室只能安排某一教学班的授课。

3.2排课系统功能分析

排课系统首先需要实现系统初始化,包括设定教学区域、校区、学年学期、学期起始周次等。此外还有信息管理功能的维护,包括院系专业基本信息、基本信息、教师基本信息、教学班基本信息、班级基本信息、课程基本信息、学生基本信息及自动导入和手动录入教室基本信息。

其次是对于某些特殊情况,比如放长假之前需要补课,又比如任课老师要出差无法按时上课,这时就需要进行手动预排课。此种情况下,班级负责人就需要去上报情况,跟教务管理人员回报需要变动的教学计划,提前查看近期空教室的情况,推迟课程,重新排课。此时,需要考虑对下次授课时间的设定以及对教室容纳量有没有特殊的要求等进行排课,然后教务人员及时录入,并挂在网站上。

再次是网上查询课表、课表打印功能。排课系统提供互联网查询功能,进行计算机排课结束后,要确保学生和任课老师能够在网上查询本学年的课程安排情况,学生能够在网上打印输出自己班级的课表,教务人员可以进行简单的调课和数据修改,还可以查询各种类型课表。

此外还包括用户管理系统和数据备份与恢复。对不同级别的用户根据不同的情况设置不同的访问权限,用户必须先通过身份认证后才能进入系统,进而进行权限范围内的其他操作。计算机系统排课还可以实现排课系统设计中数据库内的信息安全,包括将数据库中的重要数据进行备份、从备份文件中恢复错误删除掉的数据等等。

4排课系统模块设计

排课系统是各大高校每学年开学前排课的工具,排课系统的作用在于它可以方便快捷地生成课表,同时可以储存本学年的课表文档。根据排课系统的需求,结合各个院系班级的情况以及任课老师的分配,由于录入数据比较庞大,因此需要在系统中装载数据模块,完成了这个预备工作后在开始执行程序语言运行。排课系统需要涵盖班级、教师、用户管理多个模块,而且需要在每一个大的功能模块下分派数目不等的子模块,以此来减少教务人员工作的难度,同时也可以方便用户随时在互联网上查询或下载课表。

4.1基本信息设置模块

(1)班级设置模块。“班级设置”模块负责维护班级信息。班级信息设置模块包括班级所在院系,班级每学年课程节数,班级学生人数,班级班主任基本情况等。

(2)课程设置模块。“课程设置”模块负责维护学校的课程信息,课程信息设置项包括专业课程名称,课程每学年安排多少个课时,每周有多少节,是否分单双周上课,任课教师情况等。

(3)教师设置模块。计算机系统对教师设置模块的设计主要解决教师信息维护的问题,包括任课老师的姓名、电话、邮箱等基本信息,以及任课时间与地点的统计。此版块的功能同样可以根据需要添加或是删除信息等。

4.2用户管理设置模块

用户管理设置板块是编写用户的基本信息,包括用户身份认证、名称、类别、密码等。用户管理模块的作用是保证用户信息添加、删除、修改的维护工作,此外用户管理要对对不同用户权限做出审查,同时,判断该用户是对数据库的访问权限达到限制额,这样做的目的是保证用户在使用过程中的信息安全。

用户管理是对用户信息进行添加、修改、删除和查看,并对用户信息的这些方面进行维护。基本操作流程:首先,点击添加新用户,填写用户信息点击提交,添加新用户成功。其次,删除选择要删除的用户,点击确定,删除用户。再次,修改用户信息,点击修改用户信息,选择要修改的用户,点击确定,提交修改。

5结论

高校各个学年开课之前必然需要排好课表,排课任务重要并且复杂,是高校教务管理工作的难题。排课的目的在于保证学生上课有合适的地点,老师有互不冲突的教学时间,从而使每学期的教学工作能够有秩序的展开。在计算机系统广泛应用之前,处理数据以及管理排课日程由教务人员手工操作,任务繁琐,容易出错,出错之后难以及时更改,造成各种麻烦,严重影响教学效率。面向对象编程语言VB.NET,不仅十分轻松的完成编写任务,在代码输入上也大大简化了工作程序,并且这种语言完全面向对象,代码维护方便容易,解决原先不能及时更改错误的难题。本文的主要工作是基于面向对象编程语言VB.NET,以设计高校课程安排管理系统的需求为目的,设计并实现了包括教室安排、班级管理、课程设置、教师设置、用户管理四个功能模块的高校排课管理系统,该系统的实现有利于提高工作效率,实现排课系统管理的信息化和标准。

参考文献:

[1]李英杰.VB.NET2005程序设计实例教程[M].天津:天津大学出版社,2008,11.

[2]郭瑞军,王松.Visual Basic.NET数据库开发实例精粹[M].北京:电子工业出版社,2006(5):34-59.

[3]孙雪莲,冯毅夫.基于B/S模式下的高校食堂管理系统设计[M].吉林师范大学学报(自然科学版),2005,11.

[4]李春葆.VB.NET 2005程序设计教程[M].北京:清华大学出版社,2009,2.

[5]龚辉锋,赵玉意,秦立公.基于VB.6与Excel的物流软件的开发构想中国管理信息化[J].2008,12.

篇5:C语言面向对象编程学习笔记

Lua中的table就是一种对象,但是如果直接使用仍然会存在大量的问题,见如下代码:

代码如下:

Account = {balance = 0}

function Account.withdraw(v)

Account.balance = Account.balance - v

end

--下面是测试调用函数

Account.withdraw(100.00)

在上面的withdraw函数内部依赖了全局变量Account,一旦该变量发生改变,将会导致withdraw不再能正常的工作,如:

代码如下:

a = Account; Account = nil

a.withdraw(100.00)--将会导致访问空nil的错误,

这种行为明显的违反了面向对象封装性和实例独立性。要解决这一问题,我们需要给withdraw函数在添加一个参数self,他等价于Java/C++中的this,见如下修改:

代码如下:

function Account.withdraw(self,v)

self.balance = self.balance - v

end

--下面是基于修改后代码的调用:

a1 = Account; Account = nil

a1.withdraw(a1,100.00)--正常工作。

针对上述问题,Lua提供了一种更为便利的语法,即将点(.)替换为冒号(:),这样可以在定义和调用时均隐藏self参数,如:

代码如下:

function Account:withdraw(v)

self.balance = self.balance - v

end

--调用代码可改为:

a:withdraw(100.00)

1. 类:

Lua在语言上并没有提供面向对象的支持,因此想实现该功能,我们只能通过table来模拟,见如下代码及关键性注释:

代码如下:

--[[

在这段代码中,我们可以将Account视为class的声明,如Java中的:

public class Account

{

public float balance = 0;

public Account(Account o);

public void deposite(float f);

}

--]]

--这里balance是一个公有的成员变量。

Account = {balance = 0}

--new可以视为构造函数

function Account:new(o)

o = o or {} --如果参数中没有提供table,则创建一个空的。

--将新对象实例的metatable指向Account表(类),这样就可以将其视为模板了。

setmetatable(o,self)

--在将Account的__index字段指向自己,以便新对象在访问Account的函数和字段时,可被直接重定向。

self.__index = self

--最后返回构造后的对象实例

return o

end

--deposite被视为Account类的公有成员函数

function Account:deposit(v)

--这里的self表示对象实例本身

self.balance = self.balance + v

end

--下面的代码创建两个Account的对象实例

--通过Account的new方法构造基于该类的示例对象。

a = Account:new

--[[

这里需要具体解释一下,此时由于table a中并没有deposite字段,因此需要重定向到Account,

同时调用Account的deposite方法。在Account.deposite方法中,由于self(a对象)并没有balance

字段,因此在执行self.balance + v时,也需要重定向访问Account中的balance字段,其缺省值为0。

在得到计算结果后,再将该结果直接赋值给a.balance。此后a对象就拥有了自己的balance字段和值。

下次再调用该方法,balance字段的值将完全来自于a对象,而无需在重定向到Account了。

--]]

a:deposit(100.00)

print(a.balance) --输出100

b = Account:new()

b:deposit(200.00)

print(b.balance) --输出200

2. 继承:

继承也是面向对象中一个非常重要的概念,在Lua中我们仍然可以像模拟类那样来进一步实现面向对象中的继承机制,见如下代码及关键性注释:

代码如下:

--需要说明的是,这段代码仅提供和继承相关的注释,和类相关的注释在上面的代码中已经给出。

Account = {balance = 0}

function Account:new(o)

o = o or {}

setmetatable(o,self)

self.__index = self

return o

end

function Account:deposit(v)

self.balance = self.balance + v

end

function Account:withdraw(v)

if v >self.balance then

error(“Insufficient funds”)

end

self.balance = self.balance - v

end

--下面将派生出一个Account的子类,以使客户可以实现透支的功能,

SpecialAccount = Account:new()--此时SpecialAccount仍然为Account的一个对象实例

--派生类SpecialAccount扩展出的方法。

--下面这些SpecialAccount中的方法代码(getLimit/withdraw),一定要位于SpecialAccount被Account构造之后。

function SpecialAccount:getLimit()

--此时的self将为对象实例。

return self.limit or 0

end

--SpecialAccount将为Account的子类,下面的方法withdraw可以视为SpecialAccount

--重写的Account中的withdraw方法,以实现自定义的功能。

function SpecialAccount:withdraw(v)

--此时的self将为对象实例。

if v - self.balance >= self:getLimit() then

error(“Insufficient funds”)

end

self.balance = self.balance - v

end

--在执行下面的new方法时,table s的元表已经是SpecialAccount了,而不再是Account。

s = SpecialAccount:new{limit = 1000.00}

--在调用下面的deposit方法时,由于table s和SpecialAccount均未提供该方法,因此访问的仍然是

--Account的deposit方法。

s:deposit(100)

--此时的withdraw方法将不再是Account中的withdraw方法,而是SpecialAccount中的该方法。

--这是因为Lua先在SpecialAccount(即s的元表)中找到了该方法。

s:withdraw(200.00)

print(s.balance) --输出-100

3. 私密性:

私密性对于面向对象语言来说是不可或缺的,否则将直接破坏对象的封装性。Lua作为一种面向过程的脚本语言,更是没有提供这样的功能,然而和模拟支持类与继承一样,我们仍然可以在Lua中通过特殊的编程技巧来实现它,这里我们应用的是Lua中的闭包函数。该实现方式和前面两个示例中基于元表的方式有着很大的区别,见如下代码示例和关键性注释:

代码如下:

--这里我们需要一个闭包函数作为类的创建工厂

function newAccount(initialBalance)

--这里的self仅仅是一个普通的局部变量,其含义完全不同于前面示例中的self。

--这里之所以使用self作为局部变量名,也是为了方便今后的移植。比如,以后

--如果改为上面的实现方式,这里应用了self就可以降低修改的工作量了。

local self = {balance = initialBalance} --这里我们可以将self视为私有成员变量

local withdraw = function(v) self.balance = self.balance - v end

local deposit = function(v) self.balance = self.balance + v end

local getBalance = function() return self.balance end

--返回对象中包含的字段仅仅为公有方法。事实上,我们通过该种方式,不仅可以实现

--成员变量的私有性,也可以实现方法的私有性,如:

--local privateFunction = function() --do something end

--只要我们不在输出对象中包含该方法的字段即可。

return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}

end

--和前面两个示例不同的是,在调用对象方法时,不再需要self变量,因此我们可以直接使用点(.),

--而不再需要使用冒号(:)操作符了。

accl = newAccount(100.00)

--在函数newAccount返回之后,该函数内的“非局部变量”表self就不再能被外部访问了,只能通过

--该函数返回的对象的方法来操作它们。

accl.withdraw(40.00)

print(acc1.getBalance())

篇6:C语言面向对象编程学习笔记

这篇文章主要介绍了简述Python中的面向对象编程的概念,面向对象编程是Python的重要特性,需要的朋友可以参考下

面向对象编程――Object Oriented Programming,简称OOP,是一种程序设计思想,OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

我们以一个例子来说明面向过程和面向对象在程序流程上的不同之处。

假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示:

std1 = { ‘name‘: ‘Michael‘, ‘score‘: 98 }std2 = { ‘name‘: ‘Bob‘, ‘score‘: 81 }

而处理学生成绩可以通过函数实现,比如打印学生的成绩:

def print_score(std): print ‘%s: %s‘ % (std[‘name‘], std[‘score‘])

如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student这种数据类型应该被视为一个对象,这个对象拥有name和score这两个属性(Property),

如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。

class Student(object): def __init__(self, name, score): self.name = name self.score = score def print_score(self): print ‘%s: %s‘ % (self.name, self.score)

给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。面向对象的程序写出来就像这样:

bart = Student(‘Bart Simpson‘, 59)lisa = Student(‘Lisa Simpson‘, 87)bart.print_scorelisa.print_score()

面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class――Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student:

所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。

面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

小结

篇7:C语言面向对象编程学习笔记

程序设计方法一般有面向过程 (Proced ure Oriente d) 简称PO和面向对象 (Obj ect Or ien ted, 简称O O) 之分, 前者重在分析出解决问题所需要的步骤, 然后用函数把这些步骤一步一步实现, 使用的时候一个一个依次调用就可以了;而后者是把构成问题事务分解成各个对象, 建立对象的目的不是为了完成一个步骤, 而是为了描叙某个事物在整个解决问题的步骤中的行为。

面向对象的程序设计方法 (Object Oriented Programmiing, 简称OOP) 是一次程序设计方法的革命, 它把设计方法从复杂繁琐的编写程序代码的工作中解放了出来, 符合人的思维方式和现实世界, 主要是利用类和对象的概念, 使项目结构更清楚, 程序容易维护, 代码重用性强。

1 传统的面向过程的解决问题的步骤 (图1)

在这里“编写代码”中这部分代码是从头写到尾的, 也就是一个个过程组成的, 一旦执行, 在没有例外或认为终止的情况下, 会一直执行到结束。

下面以C语言为例写一个简单的程序, 看一下程序执行的过程。

例:求两个整数的和

这段程序编好后, 可以对它进行编译调试了, 最后生成可执行文件, 下面看一下执行过程。

首先, 程序中的first和next是两个相加的数, first+next则是二者的和, 当执行到

两句时, 屏幕上会显示 (图2) :

提示我们输入第一个“first”数, 比如我们输入2, 此时屏幕上会显示 (图3) :

接下去运行到

这两句时, 则会显示 (图4) :

同理会显示 (图5)

从这个程序的执行过程我们能够看到, 该程序从执行开始, 要么等待我们输入数据, 要么就一直执行下去。

下面我们在看同样的这个例题, 用vb来编写执行有什么不同。

2 Vb程序设计语言的执行步骤 (图6)

在面向过程的语言中, 是没有“设计用户界面”这个内容的, 当然, 在编写代码的之前也是要分析问题, 所不同的是, 分析好以后, 要设计用户的界面, 因为vb是windows下的一个应用程序, 它是windows下的一个应用程序窗口。

在我们设计好用户界面后, 就要编写代码了, 这个编写代码的过程和c语言是完全不同的, 下面用vb编写上一部分里用C语言解决的问题, 看看有什么不同 (图7) 。

首先是输入两个数, 然后点击sum按钮, 得到结果。

这个界面要比c容易看懂, 因为这个是windows的常规窗口, 看起来一目了然, 这个界面设计好以后, 就开始编写代码这个步骤, 对于这个程序来说, 只需要将代码写如sum按钮即可, 具体内容如下。

用vb编写这个程序, 只需要一条语句就能够完成了。

3 结语

通过以上的例题, 经过分析和比较, 很好的说明了面向过程和面向对象的语言二者之间存在的差异和联系, 但是依然存在着一定的问题, 就是所搜集的能够浅显易懂的说明这个问题的例题有限, 因此, 还需要积累更多的例题, 从深层次的去对照和学习。

摘要:为了让初学语言者更好的了解面向过程的语言和面向对象的语言之间的区别和联系, 本文通过解释面向过程和面向对象的语言运行的步骤, 用实例更好的阐述了这个问题, 使读者能够根据自己的需求来选择适合自己的编程语言。

上一篇:我敬佩的人话题初中作文下一篇:教你用PS绘制火凤凰Logo