青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

冷夜 C++ 小棧

關于C++的一些經驗與心得,還會有一些技術文摘

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  6 Posts :: 5 Stories :: 12 Comments :: 0 Trackbacks

常用鏈接

留言簿(10)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

一個有趣的現象,摘自CSDN 吹云Blog《C++從零開始(十二)——何謂面向對象編程思想》原文http://blog.csdn.net/chuiyun/archive/2004/11/26/194722.aspx

    之所以摘錄這段文章,是因為我奇怪下面的例子竟然真的能夠編譯通過--在引用的文件中篡改類的private為public就可以直接訪問私有變量,而且能夠正常訪問和賦值。
    下面是摘錄的原文,有興趣的朋友不妨也試試編個代碼試驗一下。

-------------------------------------------------------------------

封裝

    先來看現在在各類VC教程中關于對象的講解中經常能看見的如下的一個類的設計。
    class Person
    { private: char m_Name[20]; unsigned long m_Age; bool m_Sex;
      public:  const char* GetName() const;  void SetName( const char* );
               unsigned long GetAge() const; void SetAge( unsigned long );
               bool GetSex() const;          void SetSex( bool );
    };
    上面將成員變量全部定義為private,然后又提供三對Get/Set函數來存取上面的三個成員變量(因為它們是private,外界不能直接存取),這三對函數都是public的,為什么要這樣?那些教材將此稱作封裝,是對類Person的內部內存布局的封裝,這樣外界就不知道其在內存上是如何布局的并進而可以保證內存的有效性(只由類自身操作其實例)。
    首先要確認上面設計的荒謬性,它是正宗的“有門沒鎖”毫無意義。接著再看所謂的對內存布局的封裝。回想在《C++從零開始(十)》中說的為什么每個要使用類的源文件的開頭要包含相應的頭文件。假設上面是在Person.h中的聲明,然后在b.cpp中要使用類Person,本來要#include "Person.h",現在替換成下面:
    class Person
    { public: char m_Name[20]; unsigned long m_Age; bool m_Sex;
      public: const char* GetName() const;  void SetName( const char* );
              unsigned long GetAge() const; void SetAge( unsigned long );
              bool GetSex() const;          void SetSex( bool );
    };
    然后在b.cpp中照常使用類Person,如下:
    Person a, b; a.m_Age = 20; b.GetSex();
    這里就直接使用了Person::m_Age了,就算不做這樣蹩腳的動作,依舊#include "Person.h",如下:
    struct PERSON { char m_Name[20]; unsigned long m_Age; bool m_Sex; };
    Person a, b; PERSON *pP = ( PERSON* )&a; pP->m_Age = 40;
    上面依舊直接修改了Person的實例a的成員Person::m_Age,如何能隱藏內存布局?!請回想聲明的作用,類的內存布局是編譯器生成對象時必須的,根本不能對任何使用對象的代碼隱藏有關對象實現的任何東西,否則編譯器無法編譯相應的代碼。
    那么從語義上來看。Person映射的不是真實世界中的人的概念,應該是存放某個數據庫中的某個記錄人員信息的表中的記錄的緩沖區,那么緩沖區應該具備那三對Get/Set所代表的功能嗎?緩沖區是緩沖數據用的,緩沖后被其它操作使用,就好像箱子,只是放東西用。故上面的三對Get/Set沒有存在的必要,而三個成員變量則不能是private。當然,如果Person映射的并不是緩沖區,而在其它的世界中具備像上面那樣表現的語義,則像上面那樣定義就沒有問題,但如果是因為對內存布局的封裝而那樣定義類則是大錯特錯的。
    上面錯誤的根本在于沒有理解何謂封裝。為了說明封裝,先看下MFC(Microsoft Foundation Class Library——微軟功能類庫,一個定義了許多類的庫文件,其中的絕大部分類是封裝設計。關于庫文件在說明SDK時闡述)中的類CFile的定義。從名字就可看出它映射的是操作系統中文件的概念,但它卻有這樣的成員函數——CFile::Open、CFile::Close、CFile::Read、CFile::Write,有什么問題?這四個成員函數映射的都是對文件的操作而不是文件所具備的功能,分別為打開文件、關閉文件、從文件讀數據、向文件寫數據。這不是和前面說的成員函數的語義相背嗎?上面四個操作有個共性,都是施加于文件這個資源上的操作,可以將它們叫做“被功能”,如文件具有“被打開”的功能,具有“被讀取”的功能,但應注意它們實際并不是文件的功能。
    按照原來的說法,應該將文件映射為一個結構,如FILE,然后上面的四個操作應映射成四個函數,再利用名字空間的功能,如下:
    namespace OFILE
    {
        bool Open( FILE&, … );  bool Close( FILE&, … );
        bool Read( FILE&, … );  bool Write( FILE&, … );
    }
    上面的名字空間OFILE表示里面的四個函數都是對文件的操作,但四個函數都帶有一個FILE&的參數。回想非靜態成員函數都有個隱藏的參數this,因此,一個了不起的想法誕生了。
    將所有對某種資源的操作的集合看成是一種資源,把它映射成一個類,則這個類的對象就是對某個對象的操作,此法被稱作封裝,而那個類被稱作包裝類或封裝類。很明顯,包裝類映射的是“對某種資源的操作”,是一抽象概念,即包裝類的對象都是無狀態對象(指邏輯上應該是無狀態對象,但如果多個操作間有聯系,則還是可能有狀態的,但此時它的語義也相應地有些變化。如多一個CFile::Flush成員函數,用于刷新緩沖區內容,則此時就至少有一個狀態——緩沖區,還可有一個狀態記錄是否已經調用過CFile::Write,沒有則不用刷新)。
    現在應能了解封裝的含義了。將對某種資源的操作封裝成一個類,此包裝類映射的不是世界中定義的某一“名詞性概念”,而是世界的“動詞性概念”或算法中“對某一概念的操作”這個人為定出來的抽象概念。由于包裝類是對某種資源的操作的封裝,則包裝類對象一定有個屬性指明被操作的對象,對于MFC中的CFile,就是CFile::m_hFile成員變量(類型為HANDLE),其在包裝類對象的主要運作過程(前面的CFile::Read和CFile::Write)中被讀。
    有什么好處?封裝提供了一種手段以將世界中的部分“動詞性概念”轉換成對象,使得程序的架構更加簡單(多條“動詞性概念”變成一個“名詞性概念”,減少了“動詞性概念”的數量),更趨于面向對象的編程思想。
    但應區別開包裝類對象和被包裝的對象。包裝類對象只是個外殼,而被包裝的對象一定是個具有狀態的對象,因為操作就是改變資源的狀態。對于CFile,CFile的實例是包裝類對象,其保持著一個對被包裝對象——文件內核對象(Windows操作系統中定義的一種資源,用HANDLE的實例表征)——的引用,放在CFile::m_hFile中。因此,包裝類對象是獨立于被包裝對象的。即CFile a;,此時a.m_hFile的值為0或-1,表示其引用的對象是無效的,因此如果a.Read( … );將失敗,因為操作施加的資源是無效的。對此,就應先調用a.Open( … );以將a和一特定的文件內核對象綁定起來,而調用a.Close( … );將解除綁定。注意CFile::Close調用后只是解除了綁定,并不代表a已經被銷毀了,因為a映射的并不是文件內核對象,而是對文件內核對象操作的包裝類對象。
    如果仔細想想,就會發現,老虎能夠吃兔子,兔子能夠被吃,那這里應該是老虎有個功能是“吃兔子”還是多個兔子的包裝類來封裝“吃兔子”的操作?這其實不存在任何問題,“老虎吃兔子”和“兔子被吃”完全是兩個不同的操作,前者涉及兩種資源,后者只涉及一種資源,因此可以同時實現兩者,具體應視各自在相應世界中的語義。如果對于真實世界,則可以簡略地說老虎有個“吃”的功能,可以吃“肉”,而動物從“肉”和“自主能動性”多重繼承,兔子再從動物繼承。這里有個類叫“自主能動性”,指動物具有意識,能夠自己動作,這在C++中的表現就是有成員函數的類,表示有功能可以被操作,但收音機也具有調臺等功能,難道說收音機也能自己動?!這就是世界的意義——運轉。

(本文是本人以baodi_z的網名原發表在CSDN的個人BLOG,原文發表于 2004年12月09日 2:09 PM )

posted on 2005-09-12 23:35 冷夜 閱讀(2189) 評論(8)  編輯 收藏 引用 所屬分類: C++ 經驗與技巧冷夜文摘

Feedback

# re: 關于封裝--一個有趣的C++例子 2005-09-13 09:28 atempcode
有什么奇怪。本來private就是compile time check, 不是 run time check.  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-13 20:14 冷夜
呵呵,這個我沒有研究透,所以剛開始覺得很意外  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-13 23:15 可冰
其實他這個方式不一定有效,因為C++的類成員的內存布局可以與聲明的順序不一樣,而不象C的結構中的成員一樣,要完全的一致.所以他這樣的實現有賴于編譯器的實現,而不能得到語言級的保證.  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-13 23:42 冷夜
樓上說的有理  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-16 10:42 ffox
class Person
{ private: char m_Name[20]; unsigned long m_Age; bool m_Sex;
public: const char* GetName() const; void SetName( const char* );
unsigned long GetAge() const; void SetAge( unsigned long );
bool GetSex() const; void SetSex( bool );
};
person類的設計本來就有問題,我的理解:把變量放在private中,又在public中對三個變量進行操作,這樣和把變量聲明稱public又有什么區別?不都是要對變量進行操作嗎,既然把變量放在private中,就要把對變量操作的member也同樣放在private中.  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-18 08:44 FrameSniper
沒什么可奇怪的!  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2005-09-18 17:48 可冰
@ffox:
這樣是將對變量的讀寫操作封裝起來以接口的形式提供,它在提供了一定的接口一致性.如果以后要在讀寫變量的操作內加入其它的操作,那么原有的代碼就可以不加任何修改,只改這樣的接口就行了.也就是對外部封閉了細節,使編程簡單一點.
但我也覺得不能用"一刀切"的方式將所有的成員變量都加以這樣的封裝,這樣無疑會使代碼增長(而且可能還有我所不知道的缺點).
所以,可以作如下的總結:
對于要對外部提供應用的變量,最好以接口的形式提供;而如果只是內部用的話,在用途只是用于保存變量的值的話,直接聲明為public會好一些.
具體的情況還要加以區別對待,根據實際情況加以應用.  回復  更多評論
  

# re: 關于封裝--一個有趣的C++例子 2007-07-18 17:13 pchobby
看下面阿:
class Date{
private:
int year,month,day; //日期類的 年月日
pubilc:
void setdate(int& y,int& m,int& d) const{
year=y;month=m;day=d; //向變量賦值
}

//假如我想知道現在是什么日期,怎么辦?
//倘若真要想那樣封裝,我怎么得到日期呢?直接放在public下面?!
};

關于篡改的問題,說實話俺也很驚訝,要知道兩次聲明的可不一樣啊。。。。。  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            日韩视频免费观看高清在线视频| 亚洲成人在线免费| 欧美日韩国产va另类| 国产精品视频导航| 亚洲欧洲日产国码二区| 久久精品国产v日韩v亚洲| 亚洲激情偷拍| 欧美激情四色| 久久久午夜视频| 国产精品每日更新| 亚洲人成在线观看| 国产精品狼人久久影院观看方式| 精品成人一区二区三区四区| 国产精品99久久久久久久vr| 亚洲高清激情| 看欧美日韩国产| 樱桃国产成人精品视频| 久久视频在线看| 久久国产手机看片| 黄色成人免费观看| 老鸭窝毛片一区二区三区 | 久久国产综合精品| 美女日韩欧美| 久久久国产精品一区二区中文 | 先锋影院在线亚洲| 欧美午夜片在线观看| 日韩视频中午一区| 亚洲精品免费一二三区| 免费精品99久久国产综合精品| 亚洲一区二区视频在线| 欧美精品亚洲精品| 久久久久久综合| 亚洲在线成人精品| 国产精品乱人伦中文| 先锋亚洲精品| 亚洲香蕉成视频在线观看| 国产精品久久久久久一区二区三区 | 一区二区三区蜜桃网| 亚洲精品国产精品乱码不99| 欧美日韩四区| 久久国产免费| 麻豆精品视频在线观看| 99国产成+人+综合+亚洲欧美| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 久久精品在线播放| 99v久久综合狠狠综合久久| 欧美激情成人在线视频| 日韩小视频在线观看专区| 亚洲精品永久免费| 国产精品久久久久久久久久久久久久| 亚洲一区制服诱惑| 性欧美xxxx大乳国产app| 亚洲美女精品久久| 国产精品久久久久天堂| 久久蜜桃精品| 欧美高潮视频| 性欧美办公室18xxxxhd| 国产女人18毛片水18精品| 久久精品国产清高在天天线| 亚洲欧洲日韩综合二区| 欧美插天视频在线播放| 午夜一区不卡| 亚洲精品国产品国语在线app| 亚洲天堂av电影| 亚洲精品黄网在线观看| 国产欧美1区2区3区| 欧美日韩视频在线观看一区二区三区| 午夜精品久久久久久久蜜桃app | 日韩视频在线免费观看| 欧美日韩免费观看中文| 午夜欧美视频| 99精品国产一区二区青青牛奶| 久久综合色综合88| 久久精品99国产精品酒店日本| 亚洲国产欧美一区二区三区久久| 欧美在线观看一二区| 小黄鸭精品aⅴ导航网站入口| 国产日韩欧美一区二区| 亚洲国产精品一区制服丝袜| 国产精品一二三四| 亚洲国产另类精品专区| 狠狠色狠狠色综合日日tαg| 亚洲影视综合| 一区二区免费在线播放| 久久综合五月| 欧美在线在线| 国产精品青草久久| 日韩亚洲欧美综合| 一本色道**综合亚洲精品蜜桃冫 | 美女视频一区免费观看| 亚洲观看高清完整版在线观看| 久久综合九色综合欧美狠狠| 999在线观看精品免费不卡网站| 亚洲福利av| 亚洲破处大片| 一本久久综合| 欧美在线观看一二区| 久久影院午夜片一区| 欧美α欧美αv大片| 欧美精品在线观看播放| 欧美亚一区二区| 国产在线不卡视频| 99精品视频免费全部在线| 香蕉乱码成人久久天堂爱免费| 欧美成人激情在线| 91久久久久久久久| 欧美精品在线观看| 欧美视频中文一区二区三区在线观看| 国产精品久久九九| 亚洲国产福利在线| 欧美区日韩区| 国产精品午夜在线观看| 亚洲成色777777在线观看影院| 亚洲精品在线观看免费| 久久se精品一区二区| 日韩视频中文字幕| 欧美在线视频一区二区三区| 欧美二区乱c少妇| 国产综合一区二区| 久久精品夜色噜噜亚洲aⅴ| 日韩亚洲一区在线播放| 狠狠综合久久av一区二区小说| 亚洲另类在线视频| 亚洲宅男天堂在线观看无病毒| 国产精品久久影院| 欧美视频精品在线| 欧美黄污视频| 国产欧美大片| 久久成人资源| 香蕉视频成人在线观看| 国产一区二区三区直播精品电影| 日韩视频免费观看高清完整版| 美女精品自拍一二三四| 亚洲欧美日韩在线不卡| 国产美女精品| 久久精品30| 欧美一区二区精品| 欧美日韩日日骚| 午夜精品国产| 久久av老司机精品网站导航| 激情久久久久久久| 亚洲国产精品va在线观看黑人| 亚洲一区日韩在线| 99国产精品久久久久久久成人热| 亚洲第一天堂无码专区| 99在线观看免费视频精品观看| 亚洲一区三区视频在线观看| 亚洲激情图片小说视频| 国产精品久久久久久av下载红粉 | 欧美成年人视频网站| 亚洲一区二区成人在线观看| 国语自产精品视频在线看一大j8| 欧美大片在线看| 国产精品日产欧美久久久久| 欧美福利视频| 国产精品国产亚洲精品看不卡15 | 久久久久国产精品一区二区| 六月婷婷久久| 欧美国产综合视频| 免费观看一区| 亚洲一区二区三区免费在线观看| 欧美成人免费视频| 久久久www免费人成黑人精品 | 性亚洲最疯狂xxxx高清| 亚洲福利精品| 国产欧美另类| 欧美区视频在线观看| 久久噜噜亚洲综合| 欧美一区二区视频免费观看| 亚洲午夜成aⅴ人片| 9人人澡人人爽人人精品| 最近中文字幕mv在线一区二区三区四区| 欧美专区第一页| 亚洲影院免费| 一区二区三区成人| 亚洲级视频在线观看免费1级| 国产夜色精品一区二区av| 国产精品永久| 亚洲日本久久| 国产麻豆精品theporn| 看欧美日韩国产| 久久精品中文| 欧美在线一二三区| 亚洲欧美日韩一区在线观看| 亚洲欧美日韩精品久久| 久久精品视频网| 久久久久久久尹人综合网亚洲| 性久久久久久久久久久久| 一本色道久久综合亚洲精品婷婷| 亚洲国产综合91精品麻豆| 黄色在线成人| 伊人久久综合| 1000部国产精品成人观看| 伊人狠狠色j香婷婷综合| 国产自产在线视频一区| 国产综合色产| 亚洲国产第一| 亚洲最新中文字幕| 亚洲视频欧美视频| 亚洲网站啪啪|