韋慶清+左軍+崔如春
摘要:訪問數(shù)據(jù)是面向?qū)ο蟪绦蛟O(shè)計(jì)中的重要工作。通過分析面向?qū)ο蠹夹g(shù)中的數(shù)據(jù)訪問方法,提出了直接、間接及文件流三種訪問程序中相關(guān)數(shù)據(jù)的方法,并以實(shí)例說明VC++中的引用、指針及輸入/輸出文件流在這三種數(shù)據(jù)訪問方法中的具體應(yīng)用。
關(guān)鍵詞:面向?qū)ο?;?shù)據(jù)訪問;方法;VC++
中圖分類號:TP312 文獻(xiàn)標(biāo)識碼: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++
面向?qū)ο蠹夹g(shù)是一種以對象為基礎(chǔ),以事件或消息來驅(qū)動(dòng)對象執(zhí)行處理的程序設(shè)計(jì)技術(shù)。它以數(shù)據(jù)為中心而不是以功能為中心來描述系統(tǒng),數(shù)據(jù)相對于功能而言具有更強(qiáng)的穩(wěn)定性。對象是面向?qū)ο蟪绦蛟O(shè)計(jì)的核心,而數(shù)據(jù)用于表示對象的靜態(tài)屬性,是對象的狀態(tài)信息。因此,在對數(shù)據(jù)操作過程中,選擇恰當(dāng)?shù)臄?shù)據(jù)訪問方法對正確、有效地訪問數(shù)據(jù)起到關(guān)鍵性作用,從而為程序設(shè)計(jì)的順利完成提供了有力保障。下面主要從直接訪問數(shù)據(jù)、間接訪問數(shù)據(jù)及文件流訪問數(shù)據(jù)這三個(gè)方面來分析說明在基于VC++的面向?qū)ο蟪绦蛟O(shè)計(jì)中實(shí)現(xiàn)數(shù)據(jù)訪問的具體方法。
1 直接訪問數(shù)據(jù)
1.1 訪問普通變量
面向?qū)ο蟮某绦蛟O(shè)計(jì)與面向過程的程序設(shè)計(jì)一樣,都少不了要定義和使用變量,而變量通常有兩個(gè)數(shù)
據(jù)值有待訪問,一個(gè)是其左值,另一個(gè)是其右值;要對該變量的左、右值進(jìn)行訪問可以采用直接訪問的方法。例如,有一C++語句為:int x=5;則該語句的功能作用是定義一個(gè)整型變量x,并賦其初始化值為5;變量x定義后,在后面的程序代碼中,就可以直接訪問該x變量;如語句:
int y=x; //訪問變量x的右值,把x 存儲(chǔ)單元中的數(shù)據(jù)5賦給變量y。
int *p=&x; //訪問變量x的左值,p指向x存儲(chǔ)單元,把x 存儲(chǔ)單元的地圵賦給指針變量p。
又如:int x=2,y=8;
(x>y)?x:y=10; //訪問變量的左值
int z=(x>y)?x:y; //訪問變量的右值
1.2 訪問對象
對于一個(gè)實(shí)例對象而言,同樣可以采用直接訪問的方法來訪問該對象的左、右值。和普通變量一樣,
也要遵循“先聲明,后使用”的原則。具體程序代碼說明如下:
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); } 顯然,對普通變量和實(shí)例對象的直接訪問方法簡單、方便,只需在正確定義聲明變量(對象)之后直接使用該變量名就可以了。 2 間接訪問數(shù)據(jù) 一般情況下,對數(shù)據(jù)的訪問使用直接訪問的方法就可以了,但在有些情況下,直接訪問數(shù)據(jù)可能得不到想要的結(jié)果,但如果借助于VC++語言環(huán)境下的引用或指針來實(shí)現(xiàn)對數(shù)據(jù)的間接訪問就能起到特別的功效。 2.1 使用引用訪問數(shù)據(jù) 1)使用引用訪問變量 引用(Reference)是C++獨(dú)有的特征。引用是某個(gè)變量的別名,是另一種訪問變量的方法。建立引用時(shí),要用某個(gè)變量對其初始化,于是它就被綁定在那個(gè)變量上。對于引用的改動(dòng)就是對其所綁定的變量的改動(dòng)[1],在參數(shù)傳遞中,可以實(shí)現(xiàn)按址傳遞參數(shù)的作用,從而解決按值傳遞參數(shù)時(shí)存在的問題。 例如,兩個(gè)數(shù)據(jù)交換程序代碼說明如下: #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的值為: "<
}
程序運(yùn)行結(jié)果是:i和j的值為: 3 8
原想要執(zhí)行的交換兩變量i和j值的操作沒有實(shí)現(xiàn),分析其原因在于該swap()函數(shù)調(diào)用時(shí),實(shí)際參數(shù)是按值方式傳遞給形參,在swap()函數(shù)內(nèi)部其實(shí)已經(jīng)完成了兩個(gè)形參變量數(shù)據(jù)的交換,只是其內(nèi)部數(shù)據(jù)的交換并不影響實(shí)參變量i和j的存儲(chǔ)單元中的數(shù)據(jù),它們?nèi)匀皇窃瓉淼闹?和8。而采用引用通過傳址方式來傳遞參數(shù)可以達(dá)到目的?,F(xiàn)僅將上面程序中的swap ()函數(shù)的形參修改,其他不改動(dòng)。
void swap(int& x, int& y) {
int temp ;
temp = x ;
x=y ;
y=temp;
}
程序運(yùn)行結(jié)果是:i和j的值為: 8 3
可見,通過修改swap ()函數(shù)中的形參,把原定義的數(shù)據(jù)傳遞方式改變?yōu)榘匆迷L問數(shù)據(jù)方式就可達(dá)到交換兩個(gè)實(shí)參數(shù)據(jù)的目的。
2)引用作為函數(shù)返回值
有些情況下,將引用作為函數(shù)返回值也能起到間接訪問變量左右值的作用。具體程序代碼說明如下:
#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)< } 顯然,當(dāng)執(zhí)行main()函數(shù)時(shí),語句(1)中對add()函數(shù)的調(diào)用就說明了使用其左右值的情況,即賦值表達(dá)式(等號)左邊的add函數(shù)返回值作為左值使用,而右邊的作為右值使用。 3)引用訪問對象 引用不僅能訪問普通變量,同樣可以訪問實(shí)例對象中的數(shù)據(jù)成員。具體程序代碼說明如下所示: #include class DATE{ public: DATE(int yy=0,int mm=0,int dd=0); //構(gòu)造函數(shù) void get_date(int &yy,int &mm,int &dd); //取日期到三個(gè)實(shí)參中 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="< } 程序運(yùn)行結(jié)果如圖1所示: 可見,選擇引用方式傳遞三個(gè)實(shí)參x,y,x,對象d1通過調(diào)用get_date()成員函數(shù)成功訪問了對象d1 中的私有數(shù)據(jù)。 2.2 使用指針訪問數(shù)據(jù) 指針是地址變量,指針中存儲(chǔ)的并不是所使用的數(shù)據(jù)本身,而是所要使用的數(shù)據(jù)在內(nèi)存中的地址。通過指針變量可以間接地訪問內(nèi)存單元中的數(shù)據(jù)[2]。 1)指針訪問變量 利用指針傳遞參數(shù),和引用一樣同樣可以解決按值傳遞參數(shù)時(shí)存在的問題?,F(xiàn)再將上面程序中的swap ()函數(shù)中的形參修改為指針,其他不改動(dòng)。 void swap(int *p1, int *p2) { int temp ; temp =*p1 ; *p1=*p2 ; *p2=temp; } 在主函數(shù)main()中調(diào)用函數(shù)swap(&i, &j); 程序運(yùn)行結(jié)果是:i和j的值為: 8 3 通過修改swap ()函數(shù)中的形參,借助于定義兩個(gè)指針變量來完成數(shù)據(jù)傳遞,實(shí)際上是通過指針變量間接訪問了兩個(gè)實(shí)參變量a、b,把這兩個(gè)實(shí)參變量的內(nèi)存單元中的值交換了。顯然,通過指針的間接訪問,達(dá)到了交換數(shù)據(jù)的目的。 2)指針訪問函數(shù) 在函數(shù)的定義及調(diào)用過程中,利用指針也可以間接地訪問函數(shù)及其數(shù)據(jù)。具體程序代碼說明如下:
#include
//統(tǒng)計(jì)字符串的長度
int Len(const char* string) { //函數(shù)名就是函數(shù)指針
const char* p=string;
for(int i=0;*p!='\0';i++) p++;
return i;
}
int Caller(const char* string,int (*f_p)(const char* )) { //函數(shù)指針f_p作為參數(shù)
return((*f_p)(string)); //使用函數(shù)指針執(zhí)行函數(shù)調(diào)用
}
void main(){
char *s="how are you!"; //定義指向字符串常量的指針
cout<< "字符串的長度是"< } 程序運(yùn)行結(jié)果是:字符串的長度是12 由此說明,通過函數(shù)指針可以便捷地訪問函數(shù)中的數(shù)據(jù)。 3)指針訪問對象 在C++對象模型中,只要?jiǎng)?chuàng)建每一個(gè)對象實(shí)例,系統(tǒng)都會(huì)為其分配一隱含指針this,通過該指針可以方便地訪問對象中的數(shù)據(jù)。此外,用戶還可以根據(jù)需要自定義一個(gè)類類型的指針變量,通過該指針來訪問其實(shí)例對象。對象的指針就是該對象空間的起始地址,從而達(dá)到間接訪問對象數(shù)據(jù)的目的[3]。 使用對象指針比直接使用對象更加靈活、方便。所以應(yīng)盡量使用對象指針代替對象,特別是作為函數(shù)參數(shù)或返回值時(shí),使用對象指針比使用對象本身具有更清晰的語義[4]。具體程序代碼說明如下: #include class COMPLEX{ //定義復(fù)數(shù)類COMPLEX的類界面 public: COMPLEX(double r = 0, double i = 0); //構(gòu)造函數(shù) void print(); //顯示復(fù)數(shù) COMPLEX add(const COMPLEX& other); //與另一個(gè)復(fù)數(shù)相加 protected: double real, image; //定義復(fù)數(shù)的實(shí)部與虛部 }; 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; //返回對象本身(即復(fù)數(shù)的實(shí)部和虛部) } int main(){ COMPLEX c1(1,2); //定義一個(gè)值為1 + 2i的復(fù)數(shù)c1 COMPLEX c2(2); //定義一個(gè)實(shí)部為2、虛部為缺省值0的復(fù)數(shù)c2 COMPLEX *p; //同類指針p p=&c1; //指針指向本類對象c1 p->print(); //顯示對象c1 c2.add(c1); //將c2加上c1 c2.print(); //顯示運(yùn)算后c2的值 return 0; } 程序運(yùn)行結(jié)果是:1+2i 3+2i 可見,在程序中靈活利用對象指針可以方便地訪問實(shí)例對象及其數(shù)據(jù)。 3 使用文件流訪問數(shù)據(jù) 為處理文件的輸入/輸出,VC++分別從istream類、ostream類和iostream類公有派生出了ifstream類、ofstream類和fstream類3個(gè)面向文件的流類,它們都在fstream.h文件中定義[5]。因此,文件流類在流與文件之間建立了連接,提供了以輸入文件流(ifstream類)、輸出文件流(ofstream類)及輸入/輸出文件流(fstream類)這三種文件流方式來實(shí)現(xiàn)對文件數(shù)據(jù)的訪問。 3.1 寫(輸出)數(shù)據(jù) 利用輸出文件流(ofstream)可將程序中的數(shù)據(jù)寫入到磁盤文件中。具體實(shí)現(xiàn)用以下代碼說明:把一個(gè)整數(shù)、一個(gè)浮點(diǎn)數(shù)和一個(gè)字符串寫到文本文件li1.txt中。 #include "fstream.h" int main(){ ofstream out(“l(fā)i1.txt”, ios::trunc); //創(chuàng)建輸出文件流對象并打開文件li1.txt if(!out) { cout << "can not open the file ."; return; } //向out文件流(li1.txt文件)寫入數(shù)據(jù) out << 256 << “” << 198.69 << “” << “ C++ Language\n”;
out.close();
return 0;
}
程序運(yùn)行后,將在當(dāng)前目錄下的li1.txt中寫入了256、198.69和C++ Language三個(gè)數(shù)據(jù)。
3.2 讀(輸入)數(shù)據(jù)
利用輸入文件流(ifstream)可將磁盤文件中的數(shù)據(jù)讀取到程序中。具體實(shí)現(xiàn)用以下程序代碼說明:把上述文本文件li1.txt中所存放有一個(gè)整數(shù)、一個(gè)浮點(diǎn)數(shù)和一個(gè)字符串讀取到程序中。
#include
int main(){
int x;
float y;
char str[30];
ifstream in("li1.txt"); //創(chuàng)建輸入文件流對象并打開文件li1.txt
in>>x>>y>>str; //從in文件流(li1.txt文件)中讀取數(shù)據(jù)
cout< in.close(); return 0; } 3.3 讀(輸入)/寫(輸出)數(shù)據(jù) 利用輸入/輸出文件流(fstream)可對數(shù)據(jù)進(jìn)行讀(輸入)、寫(輸出)操作。具體實(shí)現(xiàn)用以下程序代碼說明。 #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<<"請輸入學(xué)生信息:學(xué)號、姓名和成績: "< cin>>number>>name>>mark; } int main(){ const int NUM=2; Student stu[NUM]; fstream out("stu.txt",ios::out); //定義輸出文件流對象并打開文件,默認(rèn)只寫 for(int i=0;i stu[i].inputinfo(); out< out< out< } out.close(); fstream in("stu.txt",ios::in); //定義輸入文件流對象并打開文件,默認(rèn)只讀 int number; string name; int mark; for(int j=0;j in>>number>>name>>mark; //將文件數(shù)據(jù)讀出并顯示到屏幕 cout<<"第"< cout<<"學(xué)號:"< } in.close(); return 0; } 程序運(yùn)行結(jié)果如圖2所示: 由此可見,靈活利用輸入/輸出文件流(fstream)可方便地對磁盤文件數(shù)據(jù)進(jìn)行讀、寫操作。 4 結(jié)束語 綜上所述,面向?qū)ο蟪绦蛟O(shè)計(jì)中少不了對數(shù)據(jù)的訪問,如何靈活、便捷地實(shí)現(xiàn)對程序中相關(guān)數(shù)據(jù)的有效訪問將會(huì)直接影響到程序的運(yùn)行效率和應(yīng)用性能。因此,合理使用直接、間接 及文件流這三種數(shù)據(jù)訪問方法,借助VC++中的引用、指針及輸入/輸出文件流這三種數(shù)據(jù)訪問技術(shù)可以很好解決面向?qū)ο蟪绦蛟O(shè)計(jì)中對相關(guān)數(shù)據(jù)訪問的問題,為數(shù)據(jù)的正確使用提供了保障,從而確保了程序的正常運(yùn)行。 參考文獻(xiàn): [1] 甘玲, 邱勁. 面向?qū)ο蠹夹g(shù)與Visual C++[M]. 北京: 清華大學(xué)出版社, 2006. [2] 潘嘉杰. 易學(xué)C++[M]. 北京: 人民郵電出版社, 2008. [3] 譚浩強(qiáng). C++程序設(shè)計(jì)[M]. 北京: 清華大學(xué)出版社, 2008. [4] 李師賢, 李文軍, 周曉聰, 等. 面向?qū)ο蟪绦蛟O(shè)計(jì)基礎(chǔ)[M]. 2版.北京: 高等教育出版社, 2011. [5] 張海藩, 牟永敏. 面向?qū)ο蟪绦蛟O(shè)計(jì)實(shí)用教程[M]. 2版.北京: 清華大學(xué)出版社, 2007.