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\n",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() <<"\n"; } 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 \n"; threadRun(); // test use another std::cout << "GetInstancev2 method create \n"; Singleton *obj2 = Singleton::GetInstancev2(); std::cout << obj2 <<std::endl; Singleton *obj3 = Singleton::GetInstancev2(); std::cout << obj3 << std::endl; return 0; }
输出:
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__<< "\n"; } 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 << "\n after change 1 \n"; 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 << "\nwrite on copy\n"; 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; }
<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
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; }
<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; }
<7> RTTI
RTTI just compatable for a class have a virtual method