#
說(shuō)明:相關(guān)技術(shù)參考自: http://www.cublog.cn/u/18517/showart_241240.html上面這個(gè),寫的真的很不錯(cuò),通俗易懂。推薦大家去看下。下面是看完上面的文章后,自己嘗試的:
//智能指針聲明及實(shí)現(xiàn)
/************************************************************************/ /** 智能指針聲明 /************************************************************************/
#pragma once
#include <iostream> #include <stdexcept> using namespace std;
#ifndef TEST_SMARTPTR #define TEST_SMARTPTR #endif
template < class T > class TSmartPtr { public: //默認(rèn)構(gòu)造函數(shù) TSmartPtr(T* pTObject = NULL) : m_pTObject(pTObject), m_pCount(new int(1)) {} //拷貝構(gòu)造函數(shù) TSmartPtr(const TSmartPtr& src) : m_pTObject(src.m_pTObject), m_pCount(src.m_pCount) { ++(*m_pCount); } //析構(gòu)函數(shù) virtual ~TSmartPtr() { #ifdef TEST_SMARTPTR cout << "SmartPtr Object Free." << endl; #endif DoDecUseCount(); } //=重載 TSmartPtr& operator = (const TSmartPtr& rhs) { // self-assigning is also right ++*rhs.m_pCount; //源智能指針的引用計(jì)數(shù)增1 DoDecUseCount(); //目標(biāo)智能指針的引用計(jì)數(shù)減1。此非常有必要。因?yàn)樵撝羔樇热灰赶騬hs, //則說(shuō)明它就不再想去管理自身原本的指針對(duì)象了。因此需要減1() //在自身引用計(jì)數(shù)減1后,有可能自身原本維護(hù)的指針對(duì)象會(huì)被釋放掉,也有可能不會(huì)。 //(因?yàn)?,先前所管理的?duì)象,有可能還有其他的智能指針對(duì)象在維護(hù)著了。) //因此,上面這兩句才是精髓。 m_pTObject = rhs.m_pTObject; m_pCount = rhs.m_pCount; return *this; } //->重載 T* operator -> () { if (NULL != m_pTObject) return m_pTObject; throw runtime_error("access through NULL pointer"); } const T* operator -> () const { if (NULL != m_pTObject) return m_pTObject; throw runtime_error("access through NULL pointr"); } //*重載 T& operator * () { if (NULL != m_pTObject) return *m_pTObject; throw runtime_error("dereference of NULL pointer"); } const T& operator * () const { if (NULL != m_pTObject) return &m_pTObject; throw runtime_error("dereference of NULL pointer"); } private: //引用計(jì)數(shù)減1 void DoDecUseCount(void) { if (0 == --*m_pCount) { if (NULL != m_pTObject) { delete m_pTObject; m_pTObject = NULL; } delete m_pCount; m_pCount = NULL; } } T* m_pTObject; int* m_pCount; } //調(diào)用
/************************************************************************/ /** 智能指針 /************************************************************************/
// SmartPointerStu.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
#include "SmartPointer.h" #include <iostream> using namespace std;
//一個(gè)測(cè)試智能指針的類 class CMyTestClass { public: CMyTestClass() { cout << "A CMyTestClass Object was created." << endl; } virtual void Print(void) { cout << "CMyTestClass Print()." << endl; } virtual void Show(void) { cout << "CMyTestClass Show()." << endl; } ~CMyTestClass() { cout << "A CMyTestClass Object was destroied." << endl; } };
class CMyTestSubClass : public CMyTestClass { public: CMyTestSubClass() { cout << "A CMyTestSubClass Object was created." << endl; } virtual void Print(void) { cout << "CMyTestSubClass Print()." << endl; } void SubShow(void) { cout << "Sub Show()." << endl; } ~CMyTestSubClass() { cout << "A CMyTestSubClass Object was destroied." << endl; } };
int _tmain(int argc, _TCHAR* argv[]) { try { TSmartPtr<CMyTestClass> t; //因?yàn)闆](méi)有給t傳個(gè)CMyTestClass對(duì)象的指針參數(shù)進(jìn)去。所以會(huì)出異常。 t->Print(); } catch(const exception& err) { cout << err.what() << endl; } //上面這個(gè)已經(jīng)測(cè)試通過(guò)了。結(jié)果正確。 //-------------------------------------- TSmartPtr<CMyTestClass> t1(new CMyTestClass); t1->Print(); //上面這個(gè)測(cè)試->重載的操作符的正確性。測(cè)試結(jié)果是正確的。 TSmartPtr<CMyTestClass> t2(t1); t2->Print(); //上面這個(gè)測(cè)試拷貝構(gòu)造函數(shù)的正確性。測(cè)試結(jié)果是正確的。 TSmartPtr<CMyTestClass> t3(new CMyTestClass); t3 = t2; (*t3).Print(); //上面這個(gè)測(cè)試=重載的操作符的正確性。測(cè)試結(jié)果也是正確的。
TSmartPtr<CMyTestSubClass> ts4(new CMyTestSubClass); ts4->Print(); ts4->SubShow(); ts4->Show(); TSmartPtr<CMyTestSubClass> ts5(ts4); ts5->SubShow(); TSmartPtr<CMyTestSubClass> ts6 = ts5; ts6->Print(); //上面測(cè)試一下帶有繼承關(guān)系的類指針對(duì)象的智能指針使用。測(cè)試結(jié)果也是正確的。
system("pause"); return 0; }
// TemplateStu.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
#include <iostream> using namespace std;
/************************************************************************/ /** 函數(shù)模板 /************************************************************************/ template<class T> T min___(T t1, T t2) { return t1 < t2 ? t1 : t2; }
template<typename T> T max___(T t1, T t2) { return t1 > t2 ? t1 : t2; }
/************************************************************************/ /** 類模板 /************************************************************************/ template<class TA, class TB> class TShowClass { private: TA* m_pObjA; TB* m_pObjB; public: TShowClass(TA* pA, TB* pB); void Show(void); };
//類模板的構(gòu)造函數(shù) template<class TA, class TB> TShowClass<TA, TB>::TShowClass(TA* pA, TB* pB) { this->m_pObjA = pA; this->m_pObjB = pB; }
//Show函數(shù) template<class TA, class TB> void TShowClass<TA, TB>::Show() { int addA = 10000; int addB = 20000; cout << addA << endl; cout << addB << endl; }
class CClassA {
}; class CClassB {
};
int _tmain(int argc, _TCHAR* argv[]) { /************************************************************************/ /** 函數(shù)模板的調(diào)用(其實(shí)就跟變通模板的調(diào)用是一樣的) /************************************************************************/ int i = 10, j = 11; float f1 = 9.0f, f2 = 11.1f; char c1 = 'b', c2 = 'Q'; cout << min___(i, j) << endl; cout << min___(f1, f2) << endl; cout << min___(c1, c2) << endl;
cout << endl; cout << max___(i, j) << endl; cout << max___(f1, f2) << endl; cout << max___(c1, c2) << endl;
/************************************************************************/ /** 類模板的調(diào)用 /************************************************************************/ CClassA ObjA; CClassB ObjB; //TShowClass<CClassA, CClassB> ShowClassObj(&ObjA, &ObjB); //ShowClassObj.Show(); //上面兩行調(diào)用是OK的。現(xiàn)在再試下創(chuàng)建一個(gè)類模板的指針對(duì)象 typedef TShowClass<CClassA, CClassB> TSC; TSC* pShowClassObj = new TSC(&ObjA, &ObjB); pShowClassObj->Show(); delete pShowClassObj; pShowClassObj = NULL;
/************************************************************************/ /** 模板使用總結(jié): /** 1) 不論是函數(shù)模板還是類模板。都必須以:template<class TA[, class TB, ]>[的內(nèi)容是可選的,但至少要有一個(gè)] /** 2) 對(duì)于函數(shù)模板,則自1)步驟后,剩下的同寫一個(gè)普通函數(shù)的步驟是一模一樣的。 /** 3) 對(duì)于類模板,則自1)步驟后,剩下的同寫一個(gè)普通的類的步驟是一模一樣的。 /** 4) 對(duì)于類模板,它們的具體cpp實(shí)現(xiàn),需要注意:普通類的實(shí)現(xiàn)前只是需要加上返回類型及類型前綴即可。而 /** 對(duì)類模板的具體實(shí)現(xiàn)卻是: /** template<class TA, class TB> /** TShowClass<TA, TB>::TShowClass(TA* pA, TB* pB){ } /** 與 /** template<class TA, class TB> /** void TShowClass<TA, TB>::Show(){ } /** 也就是說(shuō),cpp的具體實(shí)現(xiàn)的前綴不是以前的類類型,而是類模板類型 /** /** 5) 擴(kuò)展:按上面的測(cè)試及理解,說(shuō)明智能指針,則是在類模板內(nèi)部維護(hù)一個(gè)具體實(shí)現(xiàn)對(duì)象的指針。詳細(xì)見(jiàn)智能指針的學(xué)習(xí)演示 /************************************************************************/
system("pause"); return 0; }
Memento模式 該模式的出現(xiàn),主要是為了讓用戶擁有“撤銷”的操作。好給用戶有個(gè)恢復(fù)先前狀態(tài)的權(quán)力。其主要思想就是將對(duì)象(假設(shè)其類型為:ClassA)的先前狀態(tài)記錄起來(lái)(當(dāng)然自己得管理好)。在需要時(shí),用此恢復(fù)。根據(jù)此思路,當(dāng)然實(shí)現(xiàn)方法就多種多樣。下面參考設(shè)計(jì)模式資料中的c++代碼。(覺(jué)得此代碼設(shè)計(jì)還是挺有道理的。因?yàn)閷?duì)Memento類來(lái)說(shuō),除了ClassA的對(duì)象外,其他類型的對(duì)象都不需要,且也不應(yīng)該能訪問(wèn)到。因此,在具體實(shí)現(xiàn)上,它用了友元的技術(shù))。
typedef std::string State;
class COperationsMemento { //其實(shí)更強(qiáng)的,可以將該類設(shè)計(jì)成??梢跃S護(hù)一組狀態(tài)的。這樣,就可以支持 //任意恢復(fù)到先前的第N種狀態(tài)。就好似photoshop的層的那樣的撤銷。 //為說(shuō)明思想,此暫時(shí)只維護(hù)一個(gè)狀態(tài)。 private: State GetState(void) { return this->_sta; } void SetState(const State& state) { this->_sta = state; } // some code here private: State _sta; };
class COperationSteps { public: friend class COperationsMemento; COperationSteps() { this->m_pMemento = NULL; this->_sta = "normal"; } COperationSteps(COperationsMemento* pMemento) { this->m_pMemento = pMemento; this->_sta = "normal"; } virtual ~COperationSteps() { if (m_pMemento != NULL) { delete m_pMemento; m_pMemento = NULL; } } //存儲(chǔ)狀態(tài)(即:保存狀態(tài)) void SaveState(void) { if (m_pMemento == NULL) { m_pMemento = new COperationsMemento(); } m_pMemento->SetState(this->_sta); } //恢復(fù)狀態(tài) void RestoreState(COperationsMemento* pMemento = NULL) { if (pMemento != NULL) { this->_sta = pMemento->GetState(); } else { this->_sta = m_pMemento->GetState(); } }
private: COperationsMemento* m_pMemento; //需要維護(hù),因?yàn)樵摖顟B(tài),是自己私有的 State _sta; };
// FileOp.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
//要用ifstream與ofstream進(jìn)行文件的輸入與輸出操作,必須包含此頭文件 #include <fstream> #include <iostream> #include <stdio.h>//FILE需要
int _tmain(int argc, _TCHAR* argv[]) { //技術(shù)扶自: http://www.mini188.com/showtopic-954.aspx
/************************************************************************/ /** 輸入文件流 ofstream /************************************************************************/ /* //聲明文件輸入的操作對(duì)象(輸出流對(duì)象) std::ofstream fout; //打開(kāi)一個(gè)文件,提示:如果Output.txt文件不存在,則系統(tǒng)會(huì)自動(dòng)為你創(chuàng)建一個(gè) fout.open("Output.txt"); //對(duì)文件進(jìn)行寫操作。 fout << "This is a first line." << "\n"; fout << "This is a second line." << "\n"; int num = 150; char name[] = "John Doe"; fout << "Here is a number: " << num << "\n"; fout << "Now here is a string: " << name << "\n";
//將文件流內(nèi)容保存到硬盤 fout.flush(); //關(guān)閉文件流 fout.close(); */
/************************************************************************/ /** 輸入文件流 ifstream 12 GameDev 15.45 L This is really awesome! /************************************************************************/ /* std::ifstream fin("Input.txt"); int number; float real; char letter, word[8]; fin >> number >> word >> real >> letter; char sentence[1000]; fin.getline(sentence, 1000);
fin.close(); */
/************************************************************************/ /** 文件流操作 fstream /************************************************************************/ // std::fstream fFile; // fFile.open("Output.txt", std::ios::in | std::ios::out); //fFile.open("無(wú)線iPhone平臺(tái)開(kāi)發(fā)基礎(chǔ)培訓(xùn)交流圈.jpg"); //經(jīng)測(cè)試,非文本文件資源是打不開(kāi)的。 //將整個(gè)文件的內(nèi)容讀取出來(lái),并顯示 //注意:用這種方法讀出來(lái)的,都是忽略空格與換行符的 // if (fFile.is_open()) // { // char letter; // //while (fFile.good() && !fFile.eof()) // while (!fFile.eof()) //用這個(gè)與上面那個(gè)都是一樣的效果 // { // fFile >> letter; // if (fFile.eof()) // break; // std::cout << letter << std::endl; // } // getchar(); // }
//注意:用這種方法讀限出來(lái)的,都是沒(méi)忽略末尾的換行符的 // if (fFile.is_open()) // { // char line[2048]; // while (fFile.good() && !fFile.eof()) // { // fFile.getline(line, 2048); // static int count = 0; // if (count < 3) // { // count += 1; // fFile.seekg(0, std::ios::beg); //這個(gè)是改變讀的指針位置。如果是想改變寫的指針位置用fFile.seekp(0, std::ios::beg/end); // } // std::cout << line << std::endl; // } // // //將第一行的字符串改:"The first line string is changed." // fFile.seekp(0, std::ios::beg); // //fFile << "The first line string is changed."; //寫內(nèi)容不是這樣寫的。如果是ofstream可以這么寫。但對(duì)于fstream需要用下面的方法來(lái)寫。測(cè)試結(jié)果發(fā)現(xiàn),仍是寫不進(jìn)去 // //char* pszTempForWrite = "The first line string is changed."; // //fFile.write(pszTempForWrite, strlen(pszTempForWrite)); // fFile.seekg(0, std::ios::beg); // fFile.getline(line, 2048); // std::cout << line << std::endl; // getchar(); // }
// //* fstream的其他一些方法 // //read方法 // char* pszOutputFileText = NULL; // fFile.seekg(0, std::ios::end); // int nSize; // nSize = fFile.tellg(); // //std::cout << fFile.tellg() << std::endl; // //用read方法一次性將整文件給讀取出來(lái)(注意:這些讀出來(lái)后,末性居然會(huì)帶了一個(gè)亂碼。這個(gè)郁悶。) // pszOutputFileText = new char[nSize + 1]; // fFile.seekg(0, std::ios::beg); // fFile.read(pszOutputFileText, nSize); // pszOutputFileText[nSize] = '\0'; // std::cout << pszOutputFileText << std::endl; // delete [] pszOutputFileText; // getchar(); // // fFile.close();
/************************************************************************/ /** 二進(jìn)制文件的讀寫 /************************************************************************/
/************************************************************************/ /** 字符串長(zhǎng)度 /************************************************************************/ // char* pszString = "Hello"; // std::cout << strlen(pszString) << std::endl; //輸出5 // // std::string sString = "Hello"; // std::cout << strlen(sString.c_str()) << std::endl;//輸出5 // // char szTest[5] = { 'H', 'e', 'l', 'l', 'o' }; // std::cout << szTest[5] << std::endl; //越界了,所以會(huì)報(bào)。 // getchar();
/************************************************************************/ /** 使用FILE類對(duì)文件進(jìn)行操作 (FILE在stdio.h中 /************************************************************************/ FILE* materialFile = fopen("DefaultObjectStd.material", "r"); if (materialFile == NULL) { std::cout << "Open the file \"DefaultObjectStd.material\" failure." << std::endl; return 0; }
const int MAX_COUNT =2048; char everyline[MAX_COUNT] = { '\0' }; while (fgets(everyline, MAX_COUNT, materialFile)) { std::cout << everyline; //注意:通過(guò)fgets()函數(shù)讀取出來(lái)的定符串,末尾是帶有換行符的。這與上面的是不一樣的。 }
//取得文件的長(zhǎng)度(即:文件的大小) int nMaterialFileSize; fseek(materialFile, 0, SEEK_END); nMaterialFileSize = ftell(materialFile); std::cout << std::endl << nMaterialFileSize << std::endl; getchar();
fclose(materialFile);
return 0; }
說(shuō)明: 本文來(lái)自CSDN博客:http://blog.csdn.net/goodluckyxl/archive/2005/01/19/259851.aspx
強(qiáng)制轉(zhuǎn)化四種類型可能很多人都常常忽略就象我一樣,但是有時(shí)還是比較有用的。不了解的建議看看,一些機(jī)制我也不是十分了解,只是將一些用法寫出來(lái)讓大家看看。
強(qiáng)制轉(zhuǎn)化無(wú)論從語(yǔ)法還是語(yǔ)意上看,都是c++中最難看的特征之一。但是基于c風(fēng)格的轉(zhuǎn)化的語(yǔ)義的不明確性及其一些潛在問(wèn)題。強(qiáng)制類型轉(zhuǎn)化最終還是被c++接受了。 1.static_cast運(yùn)算符號(hào) static_cast<T>(e),stroustrup讓我們可以把它看成隱含轉(zhuǎn)換的顯示的逆運(yùn)算。這個(gè)是有一定道理的,基于隱式轉(zhuǎn)化的對(duì)象類型我們可以使用static_cast轉(zhuǎn)化運(yùn)算符號(hào)。它是靜態(tài)的檢測(cè),無(wú)法運(yùn)行時(shí)檢測(cè)類型,在繼承中尤為突出。 使用范圍 <1>用于所有系統(tǒng)類型之間轉(zhuǎn)化,不能用于系統(tǒng)類型指針類型轉(zhuǎn)化 double t_d = 0; int t_i= static_cast<int>(t_d); //是合法的轉(zhuǎn)化 而企圖將double*->int*是不允許的 <2>用于繼承類之間的轉(zhuǎn)化(含指針),不能用于其他沒(méi)有隱式轉(zhuǎn)化的對(duì)象類型之間的轉(zhuǎn)化 繼承舉例: class x { }; class y: public x { }; 使用:x t_o_x; y t_o_y = static_cast<y>(t_o_x); //x* y*轉(zhuǎn)化也可以進(jìn)行因?yàn)閤,y繼承關(guān) //系,類型可以自動(dòng)隱式轉(zhuǎn)化使用 隱式轉(zhuǎn)化舉例: class x { }; class y {
public: y( x i_x ) {} }; x t_o_x; y t_o_y = static_cast<y>(t_o_x); //大家看到y(tǒng)構(gòu)造函數(shù)可以對(duì)于x類型隱式轉(zhuǎn)化 //所以可以將x->y,如果企圖將y->x會(huì)報(bào)錯(cuò) 2.reinterpret_cast 運(yùn)算 主要用于對(duì)于類型指針類型的強(qiáng)制轉(zhuǎn)化,some_type* -> special_type*這樣轉(zhuǎn)化,類型信息可以是不完全的。它允許將任意指針轉(zhuǎn)化到其他類型指針,也允許任意整數(shù)類型到任意指針類型轉(zhuǎn)化(BT)。這樣導(dǎo)致的結(jié)果是極其不安全的,不能安全的應(yīng)用于其他目的,除非轉(zhuǎn)化到原來(lái)類型。 <1> 使用所有整形可以轉(zhuǎn)化為任意類型的指針(指針是4字節(jié)的long的東東,那么機(jī)器就認(rèn)為同類型就是可以轉(zhuǎn)化) int c; x* p = reinterpret_cast<x*>(c); //x是自定義的任意類型,當(dāng)然包括系統(tǒng)類型 <2> 可以對(duì)于任意類型指針之間轉(zhuǎn)化 y* c; x* p = reinterpret_cast<x*>(c);//x,y代表所有自定義或系統(tǒng)類型 大家可以看到reinterpret_cast的轉(zhuǎn)化是極度的不負(fù)責(zé)任的,他只管轉(zhuǎn)化不檢測(cè)是否可以轉(zhuǎn)化。 <3> const_cast運(yùn)算符號(hào) 這個(gè)很簡(jiǎn)單從名字大家可以看出來(lái),僅僅為了去掉或著加上const修飾符號(hào)。但是對(duì)于本身定義時(shí)為const的類型,即使你去掉const性,在你操作這片內(nèi)容時(shí)候也要小心,只能r不能w操作,否則還是會(huì)出錯(cuò)。 const char* p = "123"; char* c = const_cast<char*>(p); c[0] = 1; //表面上通過(guò)編譯去掉了const性,但是操作其地址時(shí)系統(tǒng)依然不允許這 //么做。這是一個(gè)漏洞吧 <4> dynamic_cast運(yùn)算符號(hào) Scott Mayers將其描述為用來(lái)執(zhí)行繼承體系中:安全的向下轉(zhuǎn)型或者跨系轉(zhuǎn)型動(dòng)作。也就是說(shuō)你可以,用dynamic_cast將 指向base class的指針或引用轉(zhuǎn)型為 指向子類的對(duì)象的指針或引用。 class B {}; //polymorphic類型含virtual才能dynamic_cast class D: public B {} void f( B* pb ) { D* pd1 = dynamic_cast<D*>(pb);//如果pb為d類型正確返回,如果不是返回0 D* pd2 = static_cast<D*>(pb); //不管怎么樣都返回指針有可能指向不合適的對(duì) //象,因?yàn)閟tatic僅僅靜態(tài)檢測(cè),不能得到運(yùn) //行時(shí)對(duì)象的信息是否真正為D類型 }
反正大家在使用知道怎么用就ok了,c++強(qiáng)制轉(zhuǎn)化在模板中還是非常有用的,其他時(shí)候本人也喜歡用c的轉(zhuǎn)化方便。^_^
聲明:
1 /************************************************************************/ 2 /** 系統(tǒng)全局函數(shù) 3 /************************************************************************/ 4 5 #pragma once 6 7 #include <string> 8 9 // 取得應(yīng)用程序路徑(末尾帶 '\' 的) 10 CString ExtractFilePath(void); 11 // 取得應(yīng)用程序路徑(末尾不帶 '\' 的) 12 CString ExtractFileDir(void); 13 // 取得指定文件的目錄(參數(shù)為文件的完整路徑,返回值末尾不帶 '\' 的) 14 CString GetFileDir(const CString& csFullFileName); 15 // 取得指定文件的目錄(參數(shù)為文件的完整路徑,返回值末尾帶 '\' 的) 16 CString GetFilePath(const CString& csFullFileName); 17 // 將CString轉(zhuǎn)換成string(將Unicode串轉(zhuǎn)換成Ansi(返回string)) 18 std::string ConvertW2A(const CString& csString); 19 // 將路徑中的指定字符用另外的指定字符替換,并返回(string) 20 std::string StringReplace(const char* pszString, const char cSourceChar, const char cDestChar); 實(shí)現(xiàn):
1 #include "stdafx.h" 2 #include "GlobalFunction.h" 3 #include <atlconv.h> 4 5 CString ExtractFileDir(void) 6 { 7 CString csResult; 8 WCHAR pszExeFullPath[MAX_PATH]; 9 ::GetModuleFileName(NULL, pszExeFullPath, MAX_PATH); 10 csResult = pszExeFullPath; 11 int iPos = csResult.ReverseFind('\\'); 12 csResult = csResult.Left(iPos); 13 return csResult; 14 } 15 16 CString ExtractFilePath(void) 17 { 18 CString csResult = ExtractFileDir(); 19 if (csResult.GetLength() > 0) 20 return csResult + L"\\"; 21 return csResult; 22 } 23 24 CString GetFileDir(const CString& csFullFileName) 25 { 26 if (!::PathFileExists(csFullFileName)) 27 return CString(L""); 28 29 CString csResult(csFullFileName); 30 int iPos = csResult.ReverseFind('\\'); 31 csResult = csResult.Left(iPos); 32 return csResult; 33 } 34 35 CString GetFilePath(const CString& csFullFileName) 36 { 37 CString csResult = GetFileDir(csFullFileName); 38 if (csResult.GetLength() > 0) 39 csResult + "\\"; 40 return csResult; 41 } 42 43 std::string ConvertW2A(const CString& csString) 44 { 45 USES_CONVERSION; 46 return std::string(W2A(csString)); 47 } 48 49 std::string StringReplace(const char* pszString, const char cSourceChar, const char cDestChar) 50 { 51 if (strlen(pszString) == 0) 52 return std::string(""); 53 const UINT iLen = strlen(pszString) + 1; 54 char* pszTargetString = new char[iLen]; 55 //char pszTargetString[iLen]; 56 try 57 { 58 strncpy(pszTargetString, pszString, iLen); 59 for (int iIndex = 0; iIndex != iLen; iIndex++) 60 { 61 if (pszTargetString[iIndex] == cSourceChar) 62 pszTargetString[iIndex] = cDestChar; 63 } 64 delete [] pszTargetString; 65 return std::string(pszTargetString); 66 } 67 catch ( ) 68 { 69 delete [] pszTargetString; 70 return std::string(""); 71 } 72 }
該模式也相對(duì)簡(jiǎn)單。其主要處理的是這類問(wèn)題:當(dāng)系統(tǒng)或某些模塊已經(jīng)成形后,突然需要增加某些功能。而這些功能的增加 在現(xiàn)有的對(duì)象中,暫時(shí)沒(méi)有辦法處理。同時(shí),卻發(fā)現(xiàn),該功能,其實(shí)另一模塊的對(duì)象卻可以處理的了。因此,就希望能夠在不修改原 有操作及系統(tǒng)結(jié)構(gòu)的情況下,就自然而然地將該功能實(shí)現(xiàn)出來(lái)。此時(shí),就可以使用Adapter來(lái)處理之。(注:在此,我們強(qiáng)調(diào)的是不 去修改原有系統(tǒng)的結(jié)構(gòu)的情況下)。 就上述問(wèn)題,Adapter模式有兩種解決方法。一種是通過(guò)對(duì)象適配來(lái)解決。另一種是通過(guò)類適配來(lái)解決。所謂的對(duì)象適配,指 的是,通過(guò)引入具有我們需要功能接口的對(duì)象(設(shè)類為X),在實(shí)現(xiàn)處理過(guò)程中,我們使用的是X的功能接口,以此來(lái)達(dá)到我們的需求。 而類適配,則指的是,產(chǎn)生一個(gè)新類,讓該新類,繼承自X類,則自然,該新類就會(huì)有了X的相關(guān)接口。下面看下,這兩種適配的代碼。
對(duì)象適配 class X { public: ... virtual func(...); };
class ObjAdapterObject : public ... { public: void func(...) { if (m_pXObj != NULL) m_pXObj->func(...); } private: X* m_pXObj; };
類適配 class X的聲明及定義同上。
class ClassAdapterObject: public X, public ... { public: ... };
以下調(diào)用就不寫了,你懂得的。
|