积木

No sub title

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

常用链接

留言簿(1)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

#

说明:相关技术参考自:http://www.cublog.cn/u/18517/showart_241240.html
上面这个,写的真的很不错,通俗易懂。推荐大家去看下。下面是看完上面的文章后,自己尝试的:
//智能指针声明及实现

/************************************************************************/
/** 智能指针声明
/***********************************************************************
*/

#pragma once

#include 
<iostream>
#include 
<stdexcept>
using namespace std;

#ifndef TEST_SMARTPTR
#define TEST_SMARTPTR
#endif

template 
< class T >
class TSmartPtr
{
public:
    
//默认构造函数
    TSmartPtr(T* pTObject = NULL) : m_pTObject(pTObject), m_pCount(new int(1)) {}
    
//拷贝构造函数
    TSmartPtr(const TSmartPtr& src) : m_pTObject(src.m_pTObject), m_pCount(src.m_pCount) { ++(*m_pCount); }
    
//析构函数
    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;    //源智能指针的引用计数增1
        DoDecUseCount();    //目标智能指针的引用计数减1。此非常有必要。因为该指针既然要指向rhs,
                            
//则说明它就不再想去管理自身原本的指针对象了。因此需要减1()
                            
//在自身引用计数减1后,有可能自身原本维护的指针对象会被释放掉,也有可能不会。
                            
//(因为,先前所管理的对象,有可能还有其他的智能指针对象在维护着了。)
                            
//因此,上面这两句才是精髓。
        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:
    
//引用计数减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;
}

//调用
/************************************************************************/
/** 智能指针
/***********************************************************************
*/

// SmartPointerStu.cpp : Defines the entry point for the console application.
//

#include 
"stdafx.h"

#include 
"SmartPointer.h"
#include 
<iostream>
using namespace std;

//一个测试智能指针的类
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;    //因为没有给t传个CMyTestClass对象的指针参数进去。所以会出异常。
        t->Print();
    }
    
catch(const exception& err)
    {
        cout 
<< err.what() << endl;
    }
    
//上面这个已经测试通过了。结果正确。
    
//--------------------------------------
    TSmartPtr<CMyTestClass> t1(new CMyTestClass);
    t1
->Print();
    
//上面这个测试->重载的操作符的正确性。测试结果是正确的。
    TSmartPtr<CMyTestClass> t2(t1);
    t2
->Print();
    
//上面这个测试拷贝构造函数的正确性。测试结果是正确的。
    TSmartPtr<CMyTestClass> t3(new CMyTestClass);
    t3 
= t2;
    (
*t3).Print();
    
//上面这个测试=重载的操作符的正确性。测试结果也是正确的。

    TSmartPtr
<CMyTestSubClass> ts4(new CMyTestSubClass);
    ts4
->Print();
    ts4
->SubShow();
    ts4
->Show();
    TSmartPtr
<CMyTestSubClass> ts5(ts4);
    ts5
->SubShow();
    TSmartPtr
<CMyTestSubClass> ts6 = ts5;
    ts6
->Print();
    
//上面测试一下带有继承关系的类指针对象的智能指针使用。测试结果也是正确的。

    system(
"pause");
    
return 0;
}

posted @ 2011-06-29 10:48 Jacc.Kim 阅读(204) | 评论 (0)编辑 收藏

// TemplateStu.cpp : Defines the entry point for the console application.
//

#include 
"stdafx.h"

#include 
<iostream>
using namespace std;


/************************************************************************/
/** 函数模板
/***********************************************************************
*/
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);
};

//类模板的构造函数
template<class TA, class TB>
TShowClass
<TA, TB>::TShowClass(TA* pA, TB* pB)
{
    
this->m_pObjA = pA;
    
this->m_pObjB = pB;
}

//Show函数
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[])
{
/************************************************************************/
/** 函数模板的调用(其实就跟变通模板的调用是一样的)
/***********************************************************************
*/
    
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;


/************************************************************************/
/** 类模板的调用
/***********************************************************************
*/
    CClassA ObjA;
    CClassB ObjB;
    
//TShowClass<CClassA, CClassB> ShowClassObj(&ObjA, &ObjB);
    
//ShowClassObj.Show();
    
//上面两行调用是OK的。现在再试下创建一个类模板的指针对象
    typedef TShowClass<CClassA, CClassB> TSC;
    TSC
* pShowClassObj = new TSC(&ObjA, &ObjB);
    pShowClassObj
->Show();
    delete pShowClassObj;
    pShowClassObj 
= NULL;


/************************************************************************/
/** 模板使用总结:
/**    1) 不论是函数模板还是类模板。都必须以:template<class TA[, class TB, ]>[的内容是可选的,但至少要有一个]
/** 2) 对于函数模板,则自1)步骤后,剩下的同写一个普通函数的步骤是一模一样的。
/** 3) 对于类模板,则自1)步骤后,剩下的同写一个普通的类的步骤是一模一样的。
/** 4) 对于类模板,它们的具体cpp实现,需要注意:普通类的实现前只是需要加上返回类型及类型前缀即可。而
/**    对类模板的具体实现却是:
/**    template<class TA, class TB>
/**    TShowClass<TA, TB>::TShowClass(TA* pA, TB* pB){  }
/**    与
/**    template<class TA, class TB>
/**    void TShowClass<TA, TB>::Show(){  }
/**    也就是说,cpp的具体实现的前缀不是以前的类类型,而是类模板类型
/**    
/** 5) 扩展:按上面的测试及理解,说明智能指针,则是在类模板内部维护一个具体实现对象的指针。详细见智能指针的学习演示
/***********************************************************************
*/

    system(
"pause");
    
return 0;
}

posted @ 2011-06-28 12:03 Jacc.Kim 阅读(155) | 评论 (0)编辑 收藏

Mediator模式
      该模型主要解决两个或多个对象间的相互通信的问题。(个人认为该模式的思想同Observer模式的思想还是有点类似的。表面上看,他们所解决的问题类型根本不同,那为什么我会这么认为了?后面再说明)。按理说,各对象间的通信假如:ObjA与ObjB要进行通信。方法有好多种。比如:可以在它们内部各存一份对方的引用。在一方变动时,调用另一方进行同步即可。但确实如果系统大而复杂时,这将显示的不那么清晰。因此,就希望中间会有个调停者。Mediator模式就因此而生。此时,ObjA与ObjB内部只存为一份Mediator(MediatorObj)对象的引用。在对象变动时,只需调用MediatorObj的相关接口,通知其他对象需要同步更新即可。因此,对ObjA或ObjB或其他的任何对象来说,它们有可能根本不知道还有其他的对象存在。(如:ObjA可能不知道ObjB的存在。)但通过MediatorObj对象,却达到了ObjA与ObjB的同步作用。(现在想下,是不是与Observer模式有点类似?因为,如果在Observer模式的实现上,抽象出一个IObserverable来。那通过IObserverable对象,可以通知所有View的更新)。
 

class CClassA;
class CClassB;

class CMediator
{
public:
    CMediator(){}
    CMediator(CClassA
* pObjA, CClassB* pObjB)
    {
        
this->m_pObjA = pObjA;
        
this->m_pObjB = pObjB;
    }
    
void DoSyncFromAToB(void)
    {
        
this->m_pObjB->xxx
    }
    
void DoSyncFromBToA(void)
    {
        
this->m_pObjA->xxx
    }
private:
    CClassA
* m_pObjA;
    CClassB
* m_pObjB;
};

class CClassA
{
public:
    CClassA(){}
    CClassA(CMediator
* pMediator)
    {
        
this->m_pMediator = pMediator;
    }
    
void DoAction(void)
    {
        
// do some work here
        
        
// 通知其他对象,需要同步
        this->m_pMediator->DoSyncFromAToB();
    }

private:
    CMediator
* m_pMediator;
};

class CClassB
{
public:
    CClassB(){}
    CClassB(CMediator
* pMediator)
    {
        
this->m_pMediator = pMediator;
    }
    
void DoAction(void)
    {
        
// do some work here
        
        
// 通知其他对象,需要同步
        this->m_pMediator->DoSyncFromBToA();
    }

private:
    CMediator
* m_pMediator;
};
posted @ 2011-06-28 10:26 Jacc.Kim 阅读(968) | 评论 (0)编辑 收藏

Memento模式
      该模式的出现,主要是为了让用户拥有“撤销”的操作。好给用户有个恢复先前状态的权力。其主要思想就是将对象(假设其类型为:ClassA)的先前状态记录起来(当然自己得管理好)。在需要时,用此恢复。根据此思路,当然实现方法就多种多样。下面参考设计模式资料中的c++代码。(觉得此代码设计还是挺有道理的。因为对Memento类来说,除了ClassA的对象外,其他类型的对象都不需要,且也不应该能访问到。因此,在具体实现上,它用了友元的技术)。
typedef std::string State;

class COperationsMemento
{
    
//其实更强的,可以将该类设计成。可以维护一组状态的。这样,就可以支持
    
//任意恢复到先前的第N种状态。就好似photoshop的层的那样的撤销。
    
//为说明思想,此暂时只维护一个状态。
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;
        }
    }
    
//存储状态(即:保存状态)
    void SaveState(void)
    {
        
if (m_pMemento == NULL)
        {
            m_pMemento 
= new COperationsMemento();
        }
        m_pMemento
->SetState(this->_sta);
    }
    
//恢复状态
    void RestoreState(COperationsMemento* pMemento = NULL)
    {
        
if (pMemento != NULL)
        {
            
this->_sta = pMemento->GetState();
        }
        
else
        {
            
this->_sta = m_pMemento->GetState();
        }
    }

private:
    COperationsMemento
* m_pMemento;    //需要维护,因为该状态,是自己私有的
    State _sta;
};

posted @ 2011-06-28 10:02 Jacc.Kim 阅读(314) | 评论 (0)编辑 收藏

// FileOp.cpp : Defines the entry point for the console application.
//

#include 
"stdafx.h"

//要用ifstream与ofstream进行文件的输入与输出操作,必须包含此头文件
#include <fstream>
#include 
<iostream>
#include 
<stdio.h>//FILE需要



int _tmain(int argc, _TCHAR* argv[])
{
    
//技术扶自: http://www.mini188.com/showtopic-954.aspx

/************************************************************************/
/** 输入文件流 ofstream
/***********************************************************************
*/
    
/*
    //声明文件输入的操作对象(输出流对象)
    std::ofstream fout;
    //打开一个文件,提示:如果Output.txt文件不存在,则系统会自动为你创建一个
    fout.open("Output.txt");
    //对文件进行写操作。
    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";

    //将文件流内容保存到硬盘
    fout.flush();
    //关闭文件流
    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("无线iPhone平台开发基础培训交流圈.jpg");    //经测试,非文本文件资源是打不开的。
    
    
//将整个文件的内容读取出来,并显示
    
//注意:用这种方法读出来的,都是忽略空格与换行符的
//     if (fFile.is_open())
//     {
//         char letter;
//         //while (fFile.good() && !fFile.eof())
//         while (!fFile.eof())    //用这个与上面那个都是一样的效果
//         {
//             fFile >> letter;
//             if (fFile.eof())
//                 break;
//             std::cout << letter << std::endl;
//         }
//         getchar();
//     }


    
//注意:用这种方法读限出来的,都是没忽略末尾的换行符的
//     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);    //这个是改变读的指针位置。如果是想改变写的指针位置用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.";    //写内容不是这样写的。如果是ofstream可以这么写。但对于fstream需要用下面的方法来写。测试结果发现,仍是写不进去
//         //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方法一次性将整文件给读取出来(注意:这些读出来后,末性居然会带了一个乱码。这个郁闷。)
//     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();


/************************************************************************/
/** 二进制文件的读写
/***********************************************************************
*/


/************************************************************************/
/** 字符串长度
/***********************************************************************
*/
//     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;    //越界了,所以会报。
//     getchar();


/************************************************************************/
/** 使用FILE类对文件进行操作 (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;    //注意:通过fgets()函数读取出来的定符串,末尾是带有换行符的。这与上面的是不一样的。
    }

    
//取得文件的长度(即:文件的大小)
    int nMaterialFileSize;
    fseek(materialFile, 
0, SEEK_END);
    nMaterialFileSize 
= ftell(materialFile);
    std::cout 
<< std::endl << nMaterialFileSize << std::endl;
    
    getchar();

    fclose(materialFile);
    

    
return 0;
}
posted @ 2011-06-27 18:21 Jacc.Kim 阅读(812) | 评论 (0)编辑 收藏

说明:
      本文来自CSDN博客:http://blog.csdn.net/goodluckyxl/archive/2005/01/19/259851.aspx




强制转化四种类型可能很多人都常常忽略就象我一样,但是有时还是比较有用的。不了解的建议看看,一些机制我也不是十分了解,只是将一些用法写出来让大家看看。

强制转化无论从语法还是语意上看,都是c++中最难看的特征之一。但是基于c风格的转化的语义的不明确性及其一些潜在问题。强制类型转化最终还是被c++接受了。
1.static_cast运算符号
static_cast<T>(e),stroustrup让我们可以把它看成隐含转换的显示的逆运算。这个是有一定道理的,基于隐式转化的对象类型我们可以使用static_cast转化运算符号。它是静态的检测,无法运行时检测类型,在继承中尤为突出。
使用范围
<1>用于所有系统类型之间转化,不能用于系统类型指针类型转化
  double t_d = 0;
int t_i= static_cast<int>(t_d); //是合法的转化
而企图将double*->int*是不允许的
<2>用于继承类之间的转化(含指针),不能用于其他没有隐式转化的对象类型之间的转化
继承举例:
class x
{
};
class y: public x
{
};
使用:x t_o_x;
y t_o_y = static_cast<y>(t_o_x); //x* y*转化也可以进行因为x,y继承关
//系,类型可以自动隐式转化使用
   隐式转化举例:
class x
{
};
class y
{

public:
    y( x i_x ) {}
};
    x t_o_x;
     y t_o_y = static_cast<y>(t_o_x); //大家看到y构造函数可以对于x类型隐式转化
//所以可以将x->y,如果企图将y->x会报错
2.reinterpret_cast 运算
主要用于对于类型指针类型的强制转化,some_type* -> special_type*这样转化,类型信息可以是不完全的。它允许将任意指针转化到其他类型指针,也允许任意整数类型到任意指针类型转化(BT)。这样导致的结果是极其不安全的,不能安全的应用于其他目的,除非转化到原来类型。
<1> 使用所有整形可以转化为任意类型的指针(指针是4字节的long的东东,那么机器就认为同类型就是可以转化)
int c;
x* p = reinterpret_cast<x*>(c); //x是自定义的任意类型,当然包括系统类型
<2> 可以对于任意类型指针之间转化
y* c;
x* p = reinterpret_cast<x*>(c);//x,y代表所有自定义或系统类型
大家可以看到reinterpret_cast的转化是极度的不负责任的,他只管转化不检测是否可以转化。
<3> const_cast运算符号
这个很简单从名字大家可以看出来,仅仅为了去掉或着加上const修饰符号。但是对于本身定义时为const的类型,即使你去掉const性,在你操作这片内容时候也要小心,只能r不能w操作,否则还是会出错。
const char* p = "123";
char* c = const_cast<char*>(p);
c[0] = 1;  //表面上通过编译去掉了const性,但是操作其地址时系统依然不允许这
//么做。这是一个漏洞吧
<4> dynamic_cast运算符号
Scott Mayers将其描述为用来执行继承体系中:安全的向下转型或者跨系转型动作。也就是说你可以,用dynamic_cast将 指向base class的指针或引用转型为 指向子类的对象的指针或引用。
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); //不管怎么样都返回指针有可能指向不合适的对
//象,因为static仅仅静态检测,不能得到运
//行时对象的信息是否真正为D类型
}

反正大家在使用知道怎么用就ok了,c++强制转化在模板中还是非常有用的,其他时候本人也喜欢用c的转化方便。^_^

posted @ 2011-06-24 12:30 Jacc.Kim 阅读(303) | 评论 (0)编辑 收藏

声明:
 1 /************************************************************************/
 2 /** 系统全局函数
 3 /************************************************************************/
 4 
 5 #pragma once
 6 
 7 #include <string>
 8 
 9 // 取得应用程序路径(末尾带 '\' 的)
10 CString ExtractFilePath(void);
11 // 取得应用程序路径(末尾不带 '\' 的)
12 CString ExtractFileDir(void);
13 // 取得指定文件的目录(参数为文件的完整路径,返回值末尾不带 '\' 的)
14 CString GetFileDir(const CString& csFullFileName);
15 // 取得指定文件的目录(参数为文件的完整路径,返回值末尾带 '\' 的)
16 CString GetFilePath(const CString& csFullFileName);
17 // 将CString转换成string(将Unicode串转换成Ansi(返回string))
18 std::string ConvertW2A(const CString& csString);
19 // 将路径中的指定字符用另外的指定字符替换,并返回(string)
20 std::string StringReplace(const char* pszString, const char cSourceChar, const char cDestChar);

实现:
 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 }
posted @ 2011-06-15 15:35 Jacc.Kim 阅读(583) | 评论 (0)编辑 收藏

      Strategy模式(即:策略模式)。其所要所要解决的问题,同Template模式是同一类问题。但具体的处理方式有所不同。Template则是使用:封装继承与多态的方式实现(主要是:继承与多态)。而策略模式,则主要使用继承连同“组合”的方式来实现逻辑接口的提供。因此,如果Template模式中的逻辑接口要是有许多的话,则逻辑抽象基类,将变得十分庞大而复杂。同时,不同实现类的接口将全部暴露无疑。而组合则重在将某一逻辑接口的实现通过多个对象的组合方式实现之。下面看下策略模式的结构:
 1class Strategy
 2{
 3public:
 4  //
 5  virtual void Func1(void= 0;
 6  virtual void Func2(void= 0;//这两个接口只是示例
 7  // some other interfaces here
 8}
;
 9
10class Sub1 : Strategy
11{
12public:
13  void Func1(void)
14  {
15    // do something
16  }

17  void Func2(void)
18  {
19    // do something
20  }

21}
;
22
23class Sub2 : Strategy
24{
25public:
26  void Func1(void)
27  {
28    // do something
29  }

30  void Func2(void)
31  {
32    // do something
33  }

34}
;
35
36class Strategy;
37//策略类结构
38class Context
39{
40public:
41  Context(const Strategy* pStrategyObj) : m_pStrategyObj(pStrategyObj) {}
42  // 
43  // 逻辑接口DoAction
44  void DoAction(void)
45  {
46    if (NULL != m_pStragegyObj)
47    {
48      m_pStrategyObj->Func1();
49      m_pStrategyObj->Func2();
50      // 
51    }

52  }

53}
;

 

    注意:设计模式中,更提倡优先使用组合,而非继承。详细原因,也可以从以上模式比较得出。

posted @ 2011-06-12 12:13 Jacc.Kim 阅读(276) | 评论 (0)编辑 收藏

      Template模型,其实很容易理解,相信大家平时也经常在用。其主要思想就同处理这么一类问题:有A对象,与B对象(或更多),它们的处理不同,但他们的逻辑却是相同的。因此,我们在处理这类问题时,很自然的就会想到。给它们的逻辑处理用一抽象类封装起来。用两个具体的(实现)派生类继承之。这就是Template模型的原理。
      下面是程序示例:
 1class LogicalAbstractClass
 2{
 3public:
 4     // some code here
 5    // 逻辑接口1
 6    virtual void Logical1(= 0;
 7    // 逻辑接口2
 8    virtual bool Logical2(= 0;
 9     // some other logical interfaces
10}
;
11
12class SubClassA : public LogicalAbstractClass
13{
14public:
15    void Logical1() }
16    bool Logical2() return true/false; }
17}
;
18
19class SubClassB : public LogicalAbstractClass
20{
21public:
22    void Logical1() }
23    bool Logical2() return true/false; }
24}
;
25
26int main(int argc, char* argc[])
27{
28    LogicalAbstractClass* pA = NULL;
29    LogicalAbstractClass* pB = NULL;
30    pA = new SubClassA;
31    pB = new SubClassB;
32    
33    delete pB;
34    delete pA;
35}

      补充:Delphi的code示例就不给了。一个道理。懂得思想,所有语言通用。
posted @ 2011-06-12 11:51 Jacc.Kim 阅读(246) | 评论 (0)编辑 收藏

 该模式也相对简单。其主要处理的是这类问题:当系统或某些模块已经成形后,突然需要增加某些功能。而这些功能的增加
在现有的对象中,暂时没有办法处理。同时,却发现,该功能,其实另一模块的对象却可以处理的了。因此,就希望能够在不修改原
有操作及系统结构的情况下,就自然而然地将该功能实现出来。此时,就可以使用Adapter来处理之。(注:在此,我们强调的是不
去修改原有系统的结构的情况下)。
 就上述问题,Adapter模式有两种解决方法。一种是通过对象适配来解决。另一种是通过类适配来解决。所谓的对象适配,指
的是,通过引入具有我们需要功能接口的对象(设类为X),在实现处理过程中,我们使用的是X的功能接口,以此来达到我们的需求。
而类适配,则指的是,产生一个新类,让该新类,继承自X类,则自然,该新类就会有了X的相关接口。下面看下,这两种适配的代码。

对象适配
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:
 ...
};

以下调用就不写了,你懂得的。

posted @ 2011-05-21 23:54 Jacc.Kim 阅读(343) | 评论 (0)编辑 收藏

仅列出标题
共14页: First 6 7 8 9 10 11 12 13 14