韦庆清+左军+崔如春
摘要:访问数据是面向对象程序设计中的重要工作。通过分析面向对象技术中的数据访问方法,提出了直接、间接及文件流三种访问程序中相关数据的方法,并以实例说明VC++中的引用、指针及输入/输出文件流在这三种数据访问方法中的具体应用。
关键词:面向对象;数据访问;方法;VC++
中图分类号:TP312 文献标识码:A 文章编号:1009-3044(2016)04-0019-04
Research on Data Access Method Based on Object-oriented Technology
WEI Qing-qing, ZUO-Jun, CUI Ru-chun
(School of Mechanics and Information Engineering, Foshan University, Foshan 528000, China)
Abstract: Data access is an important work in object-oriented programming. Through the analysis of object-oriented technology in VC++ data access methods, puts forward the direct, indirect and document flow three methods of access to relevant data in the program, VC++ are demonstrated by examples of references, Pointers and input/output file stream in the application of these three data access method.
Key words:Object-Oriented; data access; method; VC++
面向对象技术是一种以对象为基础,以事件或消息来驱动对象执行处理的程序设计技术。它以数据为中心而不是以功能为中心来描述系统,数据相对于功能而言具有更强的稳定性。对象是面向对象程序设计的核心,而数据用于表示对象的静态属性,是对象的状态信息。因此,在对数据操作过程中,选择恰当的数据访问方法对正确、有效地访问数据起到关键性作用,从而为程序设计的顺利完成提供了有力保障。下面主要从直接访问数据、间接访问数据及文件流访问数据这三个方面来分析说明在基于VC++的面向对象程序设计中实现数据访问的具体方法。
1 直接访问数据
1.1 访问普通变量
面向对象的程序设计与面向过程的程序设计一样,都少不了要定义和使用变量,而变量通常有两个数
据值有待访问,一个是其左值,另一个是其右值;要对该变量的左、右值进行访问可以采用直接访问的方法。例如,有一C++语句为:int x=5;则该语句的功能作用是定义一个整型变量x,并赋其初始化值为5;变量x定义后,在后面的程序代码中,就可以直接访问该x变量;如语句:
int y=x; //访问变量x的右值,把x 存储单元中的数据5赋给变量y。
int *p=&x; //访问变量x的左值,p指向x存储单元,把x 存储单元的地圵赋给指针变量p。
又如:int x=2,y=8;
(x>y)?x:y=10; //访问变量的左值
int z=(x>y)?x:y; //访问变量的右值
1.2 访问对象
对于一个实例对象而言,同样可以采用直接访问的方法来访问该对象的左、右值。和普通变量一样,
也要遵循“先声明,后使用”的原则。具体程序代码说明如下:
class Base{
int x;
public: Base(int i){ x=I;}
void show(){cout< int get(){ return x;} }; int func( const base& obj){ int y=obj.get(); //访问对象obj的右值 Base *p=&obj; //访问对象obj的左值 p->show(); cout< } void main(){ Base a(2); Func(a); } 显然,对普通变量和实例对象的直接访问方法简单、方便,只需在正确定义声明变量(对象)之后直接使用该变量名就可以了。 2 间接访问数据 一般情况下,对数据的访问使用直接访问的方法就可以了,但在有些情况下,直接访问数据可能得不到想要的结果,但如果借助于VC++语言环境下的引用或指针来实现对数据的间接访问就能起到特别的功效。 2.1 使用引用访问数据 1)使用引用访问变量 引用(Reference)是C++独有的特征。引用是某个变量的别名,是另一种访问变量的方法。建立引用时,要用某个变量对其初始化,于是它就被绑定在那个变量上。对于引用的改动就是对其所绑定的变量的改动[1],在参数传递中,可以实现按址传递参数的作用,从而解决按值传递参数时存在的问题。 例如,两个数据交换程序代码说明如下: #include void swap(int x, int y) {
int temp ;
temp = x ;
x=y ;
y=temp;
}
void main(){
int i =3, j=8;
swap( i, j);
cout<<"i和j的值为: "<
}
程序运行结果是:i和j的值为: 3 8
原想要执行的交换两变量i和j值的操作没有实现,分析其原因在于该swap()函数调用时,实际参数是按值方式传递给形参,在swap()函数内部其实已经完成了两个形参变量数据的交换,只是其内部数据的交换并不影响实参变量i和j的存储单元中的数据,它们仍然是原来的值3和8。而采用引用通过传址方式来传递参数可以达到目的。现仅将上面程序中的swap ()函数的形参修改,其他不改动。
void swap(int& x, int& y) {
int temp ;
temp = x ;
x=y ;
y=temp;
}
程序运行结果是:i和j的值为: 8 3
可见,通过修改swap ()函数中的形参,把原定义的数据传递方式改变为按引用访问数据方式就可达到交换两个实参数据的目的。
2)引用作为函数返回值
有些情况下,将引用作为函数返回值也能起到间接访问变量左右值的作用。具体程序代码说明如下:
#include
int& add(int x,int y) {
int t=0;
t=x+y;
return t; //返回局部变量t的地址
}
void main(){
int n=2,m=10;
cout<<(add(n,m)=add(n,m)+10)< } 显然,当执行main()函数时,语句(1)中对add()函数的调用就说明了使用其左右值的情况,即赋值表达式(等号)左边的add函数返回值作为左值使用,而右边的作为右值使用。 3)引用访问对象 引用不仅能访问普通变量,同样可以访问实例对象中的数据成员。具体程序代码说明如下所示: #include class DATE{ public: DATE(int yy=0,int mm=0,int dd=0); //构造函数 void get_date(int &yy,int &mm,int &dd); //取日期到三个实参中 void print_date(); //以格式(yy.mm.dd)打印日期 private: int year,month,day; }; DATE::DATE(int yy,int mm,int dd){ year=yy; month=mm; day=dd; } void DATE::get_date(int &yy,int &mm,int &dd){ yy=year; mm=month; dd=day; } void DATE::print_date(){ cout< } void main(){ int x,y,z; DATE d1(2015,12,26);//,*p; d1.print_date(); d1.get_date(x,y,z); cout<<"x="< } 程序运行结果如图1所示: 可见,选择引用方式传递三个实参x,y,x,对象d1通过调用get_date()成员函数成功访问了对象d1 中的私有数据。 2.2 使用指针访问数据 指针是地址变量,指针中存储的并不是所使用的数据本身,而是所要使用的数据在内存中的地址。通过指针变量可以间接地访问内存单元中的数据[2]。 1)指针访问变量 利用指针传递参数,和引用一样同样可以解决按值传递参数时存在的问题。现再将上面程序中的swap ()函数中的形参修改为指针,其他不改动。 void swap(int *p1, int *p2) { int temp ; temp =*p1 ; *p1=*p2 ; *p2=temp; } 在主函数main()中调用函数swap(&i, &j); 程序运行结果是:i和j的值为: 8 3 通过修改swap ()函数中的形参,借助于定义两个指针变量来完成数据传递,实际上是通过指针变量间接访问了两个实参变量a、b,把这两个实参变量的内存单元中的值交换了。显然,通过指针的间接访问,达到了交换数据的目的。 2)指针访问函数 在函数的定义及调用过程中,利用指针也可以间接地访问函数及其数据。具体程序代码说明如下:
#include
//统计字符串的长度
int Len(const char* string) { //函数名就是函数指针
const char* p=string;
for(int i=0;*p!='\0';i++) p++;
return i;
}
int Caller(const char* string,int (*f_p)(const char* )) { //函数指针f_p作为参数
return((*f_p)(string)); //使用函数指针执行函数调用
}
void main(){
char *s="how are you!"; //定义指向字符串常量的指针
cout<< "字符串的长度是"< } 程序运行结果是:字符串的长度是12 由此说明,通过函数指针可以便捷地访问函数中的数据。 3)指针访问对象 在C++对象模型中,只要创建每一个对象实例,系统都会为其分配一隐含指针this,通过该指针可以方便地访问对象中的数据。此外,用户还可以根据需要自定义一个类类型的指针变量,通过该指针来访问其实例对象。对象的指针就是该对象空间的起始地址,从而达到间接访问对象数据的目的[3]。 使用对象指针比直接使用对象更加灵活、方便。所以应尽量使用对象指针代替对象,特别是作为函数参数或返回值时,使用对象指针比使用对象本身具有更清晰的语义[4]。具体程序代码说明如下: #include class COMPLEX{ //定义复数类COMPLEX的类界面 public: COMPLEX(double r = 0, double i = 0); //构造函数 void print(); //显示复数 COMPLEX add(const COMPLEX& other); //与另一个复数相加 protected: double real, image; //定义复数的实部与虚部 }; COMPLEX::COMPLEX(double r, double i) { real = r; image = i; } void COMPLEX::print(){ cout << real; if (image > 0) cout << "+" << image << "i"; else if (image < 0) cout << image << "i"; cout << "\n"; } COMPLEX COMPLEX::add(const COMPLEX& other){ real = real + other.real; image = image + other.image; return *this; //返回对象本身(即复数的实部和虚部) } int main(){ COMPLEX c1(1,2); //定义一个值为1 + 2i的复数c1 COMPLEX c2(2); //定义一个实部为2、虚部为缺省值0的复数c2 COMPLEX *p; //同类指针p p=&c1; //指针指向本类对象c1 p->print(); //显示对象c1 c2.add(c1); //将c2加上c1 c2.print(); //显示运算后c2的值 return 0; } 程序运行结果是:1+2i 3+2i 可见,在程序中灵活利用对象指针可以方便地访问实例对象及其数据。 3 使用文件流访问数据 为处理文件的输入/输出,VC++分别从istream类、ostream类和iostream类公有派生出了ifstream类、ofstream类和fstream类3个面向文件的流类,它们都在fstream.h文件中定义[5]。因此,文件流类在流与文件之间建立了连接,提供了以输入文件流(ifstream类)、输出文件流(ofstream类)及输入/输出文件流(fstream类)这三种文件流方式来实现对文件数据的访问。 3.1 写(输出)数据 利用输出文件流(ofstream)可将程序中的数据写入到磁盘文件中。具体实现用以下代码说明:把一个整数、一个浮点数和一个字符串写到文本文件li1.txt中。 #include "fstream.h" int main(){ ofstream out(“li1.txt”, ios::trunc); //创建输出文件流对象并打开文件li1.txt if(!out) { cout << "can not open the file ."; return; } //向out文件流(li1.txt文件)写入数据 out << 256 << “” << 198.69 << “” << “ C++ Language\n”;
out.close();
return 0;
}
程序运行后,将在当前目录下的li1.txt中写入了256、198.69和C++ Language三个数据。
3.2 读(输入)数据
利用输入文件流(ifstream)可将磁盘文件中的数据读取到程序中。具体实现用以下程序代码说明:把上述文本文件li1.txt中所存放有一个整数、一个浮点数和一个字符串读取到程序中。
#include
int main(){
int x;
float y;
char str[30];
ifstream in("li1.txt"); //创建输入文件流对象并打开文件li1.txt
in>>x>>y>>str; //从in文件流(li1.txt文件)中读取数据
cout< in.close(); return 0; } 3.3 读(输入)/写(输出)数据 利用输入/输出文件流(fstream)可对数据进行读(输入)、写(输出)操作。具体实现用以下程序代码说明。 #include #include #include using namespace std; class Student{ int number; string name; int mark; public: void inputinfo(); int get_number(){ return number;} string get_name(){ return name;} int get_mark(){ return mark;} }; void Student:: inputinfo(){ cout<<"请输入学生信息:学号、姓名和成绩: "< cin>>number>>name>>mark; } int main(){ const int NUM=2; Student stu[NUM]; fstream out("stu.txt",ios::out); //定义输出文件流对象并打开文件,默认只写 for(int i=0;i stu[i].inputinfo(); out< out< out< } out.close(); fstream in("stu.txt",ios::in); //定义输入文件流对象并打开文件,默认只读 int number; string name; int mark; for(int j=0;j in>>number>>name>>mark; //将文件数据读出并显示到屏幕 cout<<"第"< cout<<"学号:"< } in.close(); return 0; } 程序运行结果如图2所示: 由此可见,灵活利用输入/输出文件流(fstream)可方便地对磁盘文件数据进行读、写操作。 4 结束语 综上所述,面向对象程序设计中少不了对数据的访问,如何灵活、便捷地实现对程序中相关数据的有效访问将会直接影响到程序的运行效率和应用性能。因此,合理使用直接、间接 及文件流这三种数据访问方法,借助VC++中的引用、指针及输入/输出文件流这三种数据访问技术可以很好解决面向对象程序设计中对相关数据访问的问题,为数据的正确使用提供了保障,从而确保了程序的正常运行。 参考文献: [1] 甘玲, 邱劲. 面向对象技术与Visual C++[M]. 北京: 清华大学出版社, 2006. [2] 潘嘉杰. 易学C++[M]. 北京: 人民邮电出版社, 2008. [3] 谭浩强. C++程序设计[M]. 北京: 清华大学出版社, 2008. [4] 李师贤, 李文军, 周晓聪, 等. 面向对象程序设计基础[M]. 2版.北京: 高等教育出版社, 2011. [5] 张海藩, 牟永敏. 面向对象程序设计实用教程[M]. 2版.北京: 清华大学出版社, 2007.