单例(Singleton)模式、观察者(Observer)模式、void*、NULL和nullptr、C的类型转换、C++的类型转换、适配器(Adapter)模式、泛型编程的思想
目录
编程思想
单例(Singleton)模式
实现思路:
- Singleton拥有一个私有构造函数,确保用户无法通过new直接实例它;
- 包含一个静态私有成员变量instance与静态公有方法Instance();
观察者(Observer)模式
在观察者模式中,观察者需要直接订阅目标事件;在目标发出内容改变的事件后,直接接收事件并作出响应,对象常是一对多关系;
观察者抽象类:
#pragma once # ifndef OBSEVER_H_1 # define OBSEVER_H_1 class Observer { public: Observer() { ; } virtual ~Observer() { ; } // 当被观察对象发生变化时,通知被观察者调用这个方法 virtual void Update(void* pArg) = 0; }; # endif
被观察者抽象类定义:
#pragma once #include#includeusing namespace std; class Observerable { public: Observerable(); virtual ~Observerable(); // 注册观察者 void Attach(Observer* pOb); // 反注册观察者 void Detach(Observer* pOb); int GetObseverCount() const { return _Obs.size(); } void DetachAll() { _Obs.clear(); } virtual void GetSomeNews(string str) { SetChange(str); } protected: void SetChange(string news); // 有变化,需要通知 private: void Notify(void* pArg); private: bool _bChange; list_Obs; };
被观察者抽象类实现:
#include "stdafx.h" #include "Observerable.h" #include "Observer.h" Observerable::Observerable():_bChange(false) { } Observerable::~Observerable(){ } // 注册观察者 void Observerable::Attach(Observer* pOb) { if (pOb == NULL) { return; } // 看看当前列表中是否有这个观察者 auto it = _Obs.begin(); for (; it != _Obs.end(); it++) { if (*it == pOb) { return; } } _Obs.push_back(pOb); } // 反注册观察者 void Observerable::Detach(Observer* pOb) { if ((pOb == NULL) || (_Obs.empty() == true)) { return; } _Obs.remove(pOb); } void Observerable::SetChange(string news) { _bChange = true; Notify( ( (void*)news.c_str() )); } void Observerable::Notify(void* pArg) { if (_bChange == false) { return; } // 看看当前列表中是否有这个观察者 auto it = _Obs.begin(); for (; it != _Obs.end(); it++) { (*it)->Update(pArg); } _bChange = false; }
应用观察者模式:
#include "stdafx.h" class News : public Observerable { public: virtual void GetSomeNews(string str) { SetChange("News: " + str); } }; class User1:public Observer { public: virtual void Update(void* pArg) { cout << "User1 Got News: " << reinterpret_cast(pArg) <<endl; } }; class User2 :public Observer { public: virtual void Update(void* pArg) { cout << "User2 Got News: " << reinterpret_cast(pArg) <<endl; } }; int main() { User1 u1; User2 u2; News n1; n1.GetSomeNews("T0"); cout << n1.GetObseverCount() << endl; // 0 n1.Attach(&u1); n1.Attach(&u2); n1.GetSomeNews("T1"); cout << n1.GetObseverCount() << endl; // 2 n1.Detach(&u2); n1.GetSomeNews("T2"); cout << n1.GetObseverCount() << endl; // 1 n1.DetachAll(); n1.GetSomeNews("T3"); cout << n1.GetObseverCount() << endl; // 0 return 0; }
void*、NULL和nullptr
- 在C语言中:
#define NULL ((void*)0)
- 在C++语言中:
#ifndef NULL #ifdef cplusplus #define NULL0 #else #define NULL ((void*)0) #endif#endif
- 在C++11中,nullptr用来替代(void*)0,NUL则只表示0;
#includeusing namespace std; void func(void* i) { cout << "func(void* i)" << endl; } void func(int i) { cout << "func(int i)" << endl; } int main() { int* pi = NULL; int* pi2 = nullptr; char* pc = NULL; char* pc2 = nullptr; func(NULL); // func(int i) func(nullptr); // func(void* i) func(pi); // func(void* i) func(pi2); // func(void* i) func(pc); // func(void* i) func(pc2); // func(void* i) return 0; }
C的类型转换
- 隐式类型转换
doublef=1.0/2;
- 显式类型转换:(类型说明符)(表达式)
double f=double(1)/double(2);
C类型转换的问题:
- 任意类型之间都可以转换,编译器无法判断其正确性;
- 难于定位:在源码中无法快速定位;
C++的类型转换
- const cast:用于转换指针或引用,去掉类型的const属性(const变量即使内存被修改,读取的值不变,参考 const变量通过指针修改 详解 )。
const int a = 10; //int* pA = &a; //类型不一致错误 int* pA = const_cast(&a); *pA = 100; cout << a; //10,编译器只对const变量的值只读取一次
- reinterpret_cast:重新解释类型(很危险),既不检查指向的内容,也不检查指针类型本身;但要求转换前后的类型所占用内存大小一致,否则将引发编译时错误。
char* a = "a"; void* b = a; char* c = reinterpret_cast(b); cout << c; //a
- static_cast:用于基本类型转换,有继承关系类对象和类指针之间转换,由程序员来确保转换是安全的,它不会产生动态转换的类型安全检查的开销。
int i = 6; double d = static_cast(i); //基本类型转换 int -> double double d2 = 5.6; int i2 = static_cast(d2); //基本类型转换 double -> int cout << d <<endl; //6 cout << i2 << endl; //5
- dynamic_cast:只能用于含有虚函数的类,必须用在多态体系中,用于类层次间的向上和向下转化;向下转化时,如果是非送的对于指针返回NULI。
class Base { public: Base() : _i(0) { ; } virtual void T() { cout << "Base:T" << _i << endl; } private: int _i; }; class Derived : public Base { public: Derived() :_j(1) { ; } virtual void T() { cout << "Derived:T" << _j << endl; } private: int _j; }; int main() { Base cb; Derived cd; Base* pcb; Derived* pcd; // 子类--》 父类 pcb = static_cast(&cd); if (pcb == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; } pcb = dynamic_cast(&cd); if (pcb == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; } // 父类--》 子类 pcd = static_cast(&cb); if (pcd == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; } pcd = dynamic_cast(&cb); //此处转换失败 if (pcd== NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; } return 0; }
适配器(Adapter)模式
适配器模式的定义参考 设计模式 | 适配器模式及典型应用 :
- 适配器将类接口转换为客户端期望的另一个接口;
- 使用适配器可防止类由于接口不兼容而一起工作;
- 适配器模式的动机是,如果可以更改接口,则可以重用现有软件;
适配者类(被适配的角色,已存在的接口):
class LegacyRectangle { public: LegacyRectangle(double x1, double y1, double x2, double y2) { _x1 = x1; _y1 = y1; _x2 = x2; _y2 = y2; } void LegacyDraw() { cout << "LegacyRectangle:: LegacyDraw()" << _x1 << " " << _y1 << " " << _x2 << " " << _y2 << endl; } private: double _x1; double _y1; double _x2; double _y2; };
目标抽象类(客户所需接口):
class Rectangle { public: virtual void Draw(string str) = 0; };
第一种适配的方式——使用多重继承:
class RectangleAdapter: public Rectangle, public LegacyRectangle { public: RectangleAdapter(double x, double y, double w, double h) : LegacyRectangle(x, y, x + w, y + h) { cout << "RectangleAdapter(int x, int y, int w, int h)" << endl; } virtual void Draw(string str) { cout << "RectangleAdapter::Draw()" << endl; LegacyDraw(); } };
第二种适配的方式——组合方式的Adapter:
class RectangleAdapter2 :public Rectangle { public: RectangleAdapter2(double x, double y, double w, double h) : _lRect(x, y, x + w, y + h) { cout << "RectangleAdapter2(int x, int y, int w, int h)" << endl; } virtual void Draw(string str) { cout << "RectangleAdapter2::Draw()" << endl; _lRect.LegacyDraw(); } private: LegacyRectangle _lRect; };
使用适配器类:
int main() { double x = 20.0, y = 50.0, w = 300.0, h = 200.0; RectangleAdapter ra(x, y, w, h); Rectangle* pR = &ra; pR->Draw("Testing Adapter"); cout << endl; RectangleAdapter2 ra2(x, y, w, h); Rectangle* pR2 = &ra2; pR2->Draw("Testing2 Adapter"); return 0; }
结果:
RectangleAdapter(int x, int y, int w, int h) RectangleAdapter::Draw() LegacyRectangle:: LegacyDraw()20 50 320 250 RectangleAdapter2(int x, int y, int w, int h) RectangleAdapter2::Draw() LegacyRectangle:: LegacyDraw()20 50 320 250
泛型编程的思想
-
如果说面向对象是一种通过间接层来调用函数,以换取一种抽象,那么泛型编程则是更直接的抽象,它不会因为间接层而损失效率;
-
不同于面向对象的动态期多态,泛型编程是一种静态期多态,通过编译器生成最直接的代码;
-
泛型编程可以将算法与特定类型、结构剥离,尽可能复用代码;
模板函数
// 模板函数 templateT max(T a, T b) { return a > b ? a:b; } //特化 template<> char* max(char* a, char* b) { return (strcmp(a, b) > 0 ? (a) : (b)); } templateint max(T1 a, T2 b) { return static_cast(a > b ? a : b); } // 模板函数的测试 cout << max(1, 2) << endl; cout << max(1.5, 3.5) << endl; cout << max('a', 'b') << endl; //b cout << max("hello", "world") << endl; //hello char* s1 = "hello"; char* s2 = "world"; cout << max(s1, s2) << endl; //world cout << max(10, 2.5) << endl; //10
模板类
// 模板类 templateclass TC { public: TC(T a, T b, T c); T Min(); T Max(); private: T _a, _b, _c; }; templateTC::TC(T a, T b, T c):_a(a), _b(b), _c(c) { ; } templateT TC::Min() { T minab = _a < _b ? _a : _b; return minab < _c ? minab : _c; } templateT TC::Max() { T maxab = _a < _b ? _b : _a; return maxab < _c ? _c : maxab; } // 模板类的测试 TCobj1(2, 4, 3); cout << obj1.Min() << endl; cout << obj1.Max() << endl; TCobj2(2.5, 4.4, 3.3); cout << obj2.Min() << endl; cout << obj2.Max() << endl; TCobj3(399950L, 455795L, 333339090L); cout << obj3.Min() << endl; cout << obj3.Max() << endl;
泛型递归
计算1+2+3...+100的值,使用泛型递归可以在编译期间计算出值:
// 1+2+3...+100 ==> n*(n+1)/2 templatestruct Sum { enum Value {N = Sum::N+n}; // Sum(n) = Sum(n-1)+n }; template<> struct Sum{ enum Value {N = 1}; // n=1 }; int main() { cout << Sum::N << endl; return 0; }