C++ 模式设计

 只写了MinGw/Linux API部分。所有相关的代码都是参考C++ API

C++ 11智能指针参考http://blog.csdn.net/zy19940906/article/details/50470087

<1>Pimpl 

pointer to the implementation

计算一个累构造消耗的时间。

AutoTimer.h

//
// Created by Administrator on 2017/3/26.
//

#ifndef MODERN_DESIGN_AUTOTIMER_H
#define MODERN_DESIGN_AUTOTIMER_H
#include <iostream>
#include <string>
#include <memory> class AutoTimer { public: explicit AutoTimer(const std::string &name); ~AutoTimer(); private: class Impl; Impl *_mimpl;
// std::unique_ptr <Impl> _mimpl; //智能指针,生命周期与类成员周期相同 };
#endif //MODERN_DESIGN_AUTOTIMER_H

AutoTimer.cpp

#include "AutoTimer.h"
#include <sys/time.h>
class AutoTimer::Impl
{
public:
    double getElapsed() const
    {
        timeval end_time;
        gettimeofday(&end_time,NULL);
        double t1 = _start_time.tv_usec / 1e6 + _start_time.tv_sec;
        double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
        return t2 - t1;
    }
    std::string _name;
    timeval _start_time;
};
AutoTimer::AutoTimer(const std::string &name):_mimpl(new AutoTimer::Impl())
{
    _mimpl->_name = name;
    gettimeofday(&_mimpl->_start_time,NULL);
}
AutoTimer::~AutoTimer()
{
    std::cout << _mimpl->_name << ":took " << _mimpl->getElapsed() << " secs" <<std::endl;
    delete _mimpl; // 如果是智能指针不需用
    _mimpl= NULL;  // 如果是智能指针不需用
}

main.cpp:

AutoTimer timer("Houdini");
AutoTimer timer2("Maya");

输出:

Maya:took 0.000999928 secs
Houdini:took 0.000999928 secs

C语言的不透明指针。。。。实现就是这么轻松随意。。。。

AutoTimer.h

#ifndef MODER_DESIGN_C_AUTOTIMER_H
#define MODER_DESIGN_C_AUTOTIMER_H
// 声明一个指向AutoTimer结构体不透明的指针
typedef struct AutoTimer *AutoTimerPtr;
AutoTimerPtr AutoTimerCreate(const char *name);
void AutoTimerDestroy(AutoTimerPtr ptr);


#endif //MODER_DESIGN_C_AUTOTIMER_H

AutoTimer.cc

#include "AutoTimer.h"
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct AutoTimer
{
    char *mName;
    timeval mStartTime;
};

AutoTimerPtr AutoTimerCreate(const char *name)
{
    AutoTimerPtr ptr = static_cast<AutoTimerPtr> (malloc(sizeof(AutoTimer))); // 因为我们用的是C++编译器,所以还是显式转换
    if(ptr)
    {
        ptr->mName = strdup(name);
        gettimeofday(&ptr->mStartTime,NULL);
    }
    return ptr;
}
static double GetElapsed(AutoTimerPtr ptr)
{
    timeval end_time;
    gettimeofday(&end_time,NULL);
    double t1 = ptr->mStartTime.tv_usec / 1e6 + ptr->mStartTime.tv_sec;
    double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
    return t2-t1;
}
void AutoTimerDestroy(AutoTimerPtr ptr)
{
    if(ptr)
    {
        printf("%s took %f secs
",ptr->mName,GetElapsed(ptr));
        free(ptr);
    }
}

main.cpp

AutoTimerPtr ptr = AutoTimerCreate("Houdini");
AutoTimerDestroy(ptr);

AutoTimerPtr ptr2 = AutoTimerCreate("Maya");
AutoTimerDestroy(ptr2);

输出:

Houdini took 0.000000 secs
Maya took 0.000000 secs
Hello, World!

<2> 单例模式:

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

class Singleton
{
public:

    static Singleton &GetInstance()
    {
        static Singleton *instance  = NULL;
        if(! instance)
        {
            std::mutex mutex;
            if(! instance)
            {
                instance = new Singleton();
            }
            mutex.unlock();
        }
        return *instance;
    }
    static Singleton *GetInstancev2()
    {
        static Singleton m_instance;
        return &m_instance;
    }


private:
    Singleton()
    {

    }
    ~Singleton()
    {

    }
    Singleton(const Singleton &);
    const Singleton &operator=(const Singleton &);


};

void threadFunc(string name,int uniqueId)
{
    std::cout << "Singleton meomery:" << name << " -> " << uniqueId << " :Object &"<<&Singleton::GetInstance() <<"
";
}
void threadRun()
{
    thread thread_01(threadFunc,"houdini",0);
    thread thread_02(threadFunc,"maya",1);
    thread thread_03(threadFunc,"blender",2);

    thread_01.join();
    thread_02.join();
    thread_03.join();


}


int main()
{
    Singleton &obj = Singleton::GetInstance();
    std::cout << &obj <<std::endl;
    //
    std::cout << "test in thread 
";
    threadRun();
    
    // test use another
    std::cout << "GetInstancev2 method create 
";
    Singleton *obj2 = Singleton::GetInstancev2();
    std::cout << obj2 <<std::endl;

    Singleton *obj3 = Singleton::GetInstancev2();
    std::cout << obj3 << std::endl;
    return 0;
}
View Code

输出:

0x3e67c0
test in thread
Singleton meomery:Singleton meomery:blender -> Singleton meomery:maya -> houdini -> 0 :Object &0x3e67c0
1 :Object &0x3e67c0
2 :Object &0x3e67c0
GetInstancev2 method create
0x4060b0
0x4060b0

<3> 工厂模式

<4> 写时复制,节省内存最好的方法就是确实需要时再分配。所有客户共享一份唯一的资源,直到其中一个想修改这份资源为止,只有在哪个时间点才回构造副本.

template <class T> class CowPtr
{
public:
    using RefPtr = std::shared_ptr<T> ;
    inline CowPtr():mPtr(0){}
    inline CowPtr(const CowPtr<T> &other):mPtr(other.mPtr)
    {
        std::cout << "copy function "<< __LINE__<< "
";
    }
    inline explicit CowPtr(T *other):mPtr(other){}
    inline T &operator*()
    {
        std::cout<< "inline T &operator*()" <<__LINE__<<std::endl;
        Detach();
        return *(mPtr.get());
    }
    inline const T &operator*() const {
        std::cout<< "inline const T &operator*() const" <<__LINE__<<std::endl;
        return *(mPtr.get());
    }
    inline T*operator->()
    {
        std::cout<< "inline T*operator->()" <<__LINE__<<std::endl;
        Detach();
        return mPtr.get();
    }
    inline const T*operator->() const {
        std::cout<< "inline const T*operator->() " << __LINE__<<std::endl;
        return mPtr.get();
    }

    inline const T*data()const
    {
        std::cout<< "inline const T*data()const " << __LINE__<<std::endl;
        return mPtr.get();
    }


    inline bool operator==(const CowPtr<T> &other) const {
        return mPtr.get() == other.mPtr.get();
    }

    inline bool operator!() const
    {
        return !mPtr.get();
    }
    inline CowPtr &operator=(T *other)
    {
        mPtr = RefPtr(other);
        return *this;
    }


private:
    inline void Detach()
    {
        T *temp = mPtr.get();
        if(temp && !mPtr.unique())
        {
            mPtr = RefPtr(new T(*temp)); //
        }
    }
    RefPtr  mPtr;

};

class WriteOnCopy
{
public:
    WriteOnCopy(){}
    std::string getValue() const
    {
        return *mData;

    }
    void setValue(const std::string &value)
    {
        mData = new std::string(value);
    }

private:
    CowPtr<std::string> mData;
};




int main()
{
    CowPtr<std::string> string1(new std::string("houdini"));
    CowPtr<std::string> string2(string1);  //copy function
    CowPtr<std::string> string3(string1);  //copy function
    string3->append("!!");
    std::cout  << *string3.data()<<std::endl;  //houdini!!
    std::cout  << *string1<<std::endl; // houdini


    std::cout << "
 after change 1 
";
    CowPtr<std::string> pr_string1(new std::string("share me"));
    char &char_ref = pr_string1->operator[](1); //use the string operator[] function
    CowPtr<std::string> pr_string2(pr_string1);
    char_ref = 'H'; // after change 'H'
    std::cout  << *(pr_string1.data())<<std::endl;  //sHare me
    std::cout  << *(pr_string2.data())<<std::endl;  //sHare me


    // use write on copy
    std::cout << "
write on copy
";
    WriteOnCopy obj1;
    obj1.setValue("hello");
    WriteOnCopy obj2 = obj1;
    std::string val = obj2.getValue();
    WriteOnCopy obj3 = obj1;
    obj3.setValue("There");
    std::cout << "obj1 get data " << obj1.getValue() <<std::endl;
    std::cout << "obj2 get data " << obj2.getValue() <<std::endl;
    std::cout << "obj3 get data " << obj3.getValue() <<std::endl;


    return 0;
}
View Code

<5>CPP Style

(1)更好的重载operator

GLY_Currency.h

#ifndef CPPSTYLE_GLY_CURRENCY_H
#define CPPSTYLE_GLY_CURRENCY_H

#include <memory>
#include <iostream>
class GLY_Currency
{
public:
    explicit GLY_Currency(int value);
    ~GLY_Currency();
    GLY_Currency(const GLY_Currency&obj);
    int getValue()const;

// these operators must be declared as member functions
    GLY_Currency &operator =  (const GLY_Currency &rhs);
    GLY_Currency &operator += (const GLY_Currency &rhs);
    GLY_Currency &operator -= (const GLY_Currency &rhs);
    GLY_Currency &operator *= (const GLY_Currency &rhs);
    GLY_Currency &operator /= (const GLY_Currency &rhs);

private:
    class Impl;
    std::unique_ptr <Impl> mImpl;
};


// these operators can (and should) be declared as free functions
inline GLY_Currency operator+(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    // 复制一份是因为lhs+=rhs 会导致 lhs更改数据,因为lhs是const,所以不用复制构造,会导致
    // 编译错误
    return GLY_Currency(lhs)+=rhs;
}
inline GLY_Currency operator-(const GLY_Currency &lhs ,const GLY_Currency &rhs)
{
    return GLY_Currency(lhs)-=rhs;
}
inline GLY_Currency operator*(const GLY_Currency &lhs ,const GLY_Currency &rhs)
{
    return GLY_Currency(lhs)*=rhs;
}
GLY_Currency operator /(const GLY_Currency &lhs, const GLY_Currency &rhs)
{
    return GLY_Currency(lhs) /= rhs;
}


inline bool operator==(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return lhs.getValue()==rhs.getValue();
}

inline bool operator!=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return !(lhs==rhs);
}
inline bool operator<(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return rhs.getValue()<rhs.getValue();
}
inline bool operator>(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return rhs < lhs;
}

inline bool operator<=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return !(rhs > rhs);
}
inline bool operator>=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
    return rhs <= lhs;
}

inline std::ostream &operator <<(std::ostream &os,const GLY_Currency &rhs)
{
    os << rhs.getValue();
    return os;
}



#endif //CPPSTYLE_GLY_CURRENCY_H
View Code

GLY_Currency.cpp

//
// Created by Administrator on 2017/5/2.
//

#include "GLY_Currency.h"
class GLY_Currency::Impl
{
public:
    int mValue;
};



GLY_Currency::GLY_Currency(int value):mImpl(new Impl)
{
    mImpl->mValue = value;
}
GLY_Currency::~GLY_Currency() {

}

GLY_Currency::GLY_Currency(const GLY_Currency &obj):mImpl(new Impl)
{
    mImpl->mValue = obj.mImpl->mValue;
}
int GLY_Currency::getValue() const {
    return mImpl->mValue;
}

GLY_Currency& GLY_Currency::operator=(const GLY_Currency &rhs) {
    if (this != &rhs)
    {
        mImpl->mValue = rhs.mImpl->mValue;
    }
    return *this;
}
GLY_Currency& GLY_Currency::operator-=(const GLY_Currency &rhs) {
    mImpl->mValue -= rhs.mImpl->mValue;
    return *this;
}
GLY_Currency& GLY_Currency::operator+=(const GLY_Currency &rhs) {
    mImpl->mValue += rhs.mImpl->mValue;
    return *this;
}

GLY_Currency& GLY_Currency::operator*=(const GLY_Currency &rhs) {
    mImpl->mValue *= rhs.mImpl->mValue;
    return *this;
}
GLY_Currency& GLY_Currency::operator/=(const GLY_Currency &rhs) {
    mImpl->mValue /= rhs.mImpl->mValue;
    return *this;
}
View Code

<6>Exception Basic

#include <iostream>


/*
// BASIC
template <typename T>
T safe_divide(T const&a,T const &b)
{
    if (b == 0)
    {
        const char *error = "b is zero do not allowed ";
        throw error;
    }
    return a/b;
}

int main()
{
    double result = 0.0 ;
    try
    {
        result = safe_divide(2.0,0.0);
    }
    catch (const char*s)
    {
        std::cout << s <<std::endl; // will get const char *error = "b is zero do not allowed "

        //try to use right arg
        result = safe_divide(2.0,1.0);
    }

    std::cout << result <<std::endl;
    return 0;
}*/



// Use class handle the error
class ClassBad_divide_Except
{
private:
    double v1;
    double v2;
public:
    ClassBad_divide_Except(double a=0.0,double b=0.0):v1(a),v2(b){

    }
    void mesg()
    {
        const char* mesgs = "Error divide argments :";
        std::cout <<mesgs << v1<<"/"<<v2<<std::endl;
    }
};


template <typename T>
T safe_divide(T const&a,T const &b)
{
    if (b == 0)
    {
        const char *error = "b is zero do not allowed ";
        throw ClassBad_divide_Except(a,b); //emit a class instance ClassBad_divide_Except()
    }
    return a/b;
}


int main()
{
    double result = 0.0 ;
    try
    {
        result = safe_divide(2.0,0.0);
    }
    catch (ClassBad_divide_Except &did) // get class ref
    {
        did.mesg(); // get error message

        //try to use right arg
        result = safe_divide(2.0,1.0);
    }

    std::cout << result <<std::endl;
    return 0;
}
View Code

<7> RTTI

RTTI just compatable for a class have a virtual method  

原文地址:https://www.cnblogs.com/gearslogy/p/6623422.html