经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++学习笔记之编程思想 - time-flies
来源:cnblogs  作者:time-flies  时间:2021/5/24 10:58:33  对本文有异议

编程思想

单例(Singleton)模式

实现思路:

  • Singleton拥有一个私有构造函数,确保用户无法通过new直接实例它;
  • 包含一个静态私有成员变量instance静态公有方法Instance()

观察者(Observer)模式

在观察者模式中,观察者需要直接订阅目标事件;在目标发出内容改变的事件后,直接接收事件并作出响应,对象常是一对多关系;

观察者抽象类:

  1. #pragma once
  2. # ifndef OBSEVER_H_1
  3. # define OBSEVER_H_1
  4. class Observer
  5. {
  6. public:
  7. Observer() { ; }
  8. virtual ~Observer() { ; }
  9. // 当被观察对象发生变化时,通知被观察者调用这个方法
  10. virtual void Update(void* pArg) = 0;
  11. };
  12. # endif

被观察者抽象类定义:

  1. #pragma once
  2. #include <string>
  3. #include <list>
  4. using namespace std;
  5. class Observerable
  6. {
  7. public:
  8. Observerable();
  9. virtual ~Observerable();
  10. // 注册观察者
  11. void Attach(Observer* pOb);
  12. // 反注册观察者
  13. void Detach(Observer* pOb);
  14. int GetObseverCount() const
  15. {
  16. return _Obs.size();
  17. }
  18. void DetachAll()
  19. {
  20. _Obs.clear();
  21. }
  22. virtual void GetSomeNews(string str)
  23. {
  24. SetChange(str);
  25. }
  26. protected:
  27. void SetChange(string news); // 有变化,需要通知
  28. private:
  29. void Notify(void* pArg);
  30. private:
  31. bool _bChange;
  32. list<Observer*> _Obs;
  33. };

被观察者抽象类实现:

  1. #include "stdafx.h"
  2. #include "Observerable.h"
  3. #include "Observer.h"
  4. Observerable::Observerable():_bChange(false) { }
  5. Observerable::~Observerable(){ }
  6. // 注册观察者
  7. void Observerable::Attach(Observer* pOb)
  8. {
  9. if (pOb == NULL) { return; }
  10. // 看看当前列表中是否有这个观察者
  11. auto it = _Obs.begin();
  12. for (; it != _Obs.end(); it++)
  13. {
  14. if (*it == pOb) { return; }
  15. }
  16. _Obs.push_back(pOb);
  17. }
  18. // 反注册观察者
  19. void Observerable::Detach(Observer* pOb)
  20. {
  21. if ((pOb == NULL) || (_Obs.empty() == true)) { return; }
  22. _Obs.remove(pOb);
  23. }
  24. void Observerable::SetChange(string news)
  25. {
  26. _bChange = true;
  27. Notify( ( (void*)news.c_str() ));
  28. }
  29. void Observerable::Notify(void* pArg)
  30. {
  31. if (_bChange == false) { return; }
  32. // 看看当前列表中是否有这个观察者
  33. auto it = _Obs.begin();
  34. for (; it != _Obs.end(); it++)
  35. {
  36. (*it)->Update(pArg);
  37. }
  38. _bChange = false;
  39. }

应用观察者模式:

  1. #include "stdafx.h"
  2. class News : public Observerable
  3. {
  4. public:
  5. virtual void GetSomeNews(string str)
  6. {
  7. SetChange("News: " + str);
  8. }
  9. };
  10. class User1:public Observer
  11. {
  12. public:
  13. virtual void Update(void* pArg)
  14. {
  15. cout << "User1 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
  16. }
  17. };
  18. class User2 :public Observer
  19. {
  20. public:
  21. virtual void Update(void* pArg)
  22. {
  23. cout << "User2 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
  24. }
  25. };
  26. int main()
  27. {
  28. User1 u1;
  29. User2 u2;
  30. News n1;
  31. n1.GetSomeNews("T0");
  32. cout << n1.GetObseverCount() << endl; // 0
  33. n1.Attach(&u1);
  34. n1.Attach(&u2);
  35. n1.GetSomeNews("T1");
  36. cout << n1.GetObseverCount() << endl; // 2
  37. n1.Detach(&u2);
  38. n1.GetSomeNews("T2");
  39. cout << n1.GetObseverCount() << endl; // 1
  40. n1.DetachAll();
  41. n1.GetSomeNews("T3");
  42. cout << n1.GetObseverCount() << endl; // 0
  43. return 0;
  44. }

void*、NULL和nullptr

  • 在C语言中:
  1. #define NULL ((void*)0)
  • 在C++语言中:
  1. #ifndef NULL
  2. #ifdef cplusplus
  3. #define NULL0
  4. #else
  5. #define NULL ((void*)0)
  6. #endif#endif
  • 在C++11中,nullptr用来替代(void*)0,NUL则只表示0
  1. #include <iostream>
  2. using namespace std;
  3. void func(void* i) { cout << "func(void* i)" << endl; }
  4. void func(int i) { cout << "func(int i)" << endl; }
  5. int main()
  6. {
  7. int* pi = NULL;
  8. int* pi2 = nullptr;
  9. char* pc = NULL;
  10. char* pc2 = nullptr;
  11. func(NULL); // func(int i)
  12. func(nullptr); // func(void* i)
  13. func(pi); // func(void* i)
  14. func(pi2); // func(void* i)
  15. func(pc); // func(void* i)
  16. func(pc2); // func(void* i)
  17. return 0;
  18. }

C的类型转换

  • 隐式类型转换
  1. doublef=1.0/2;
  • 显式类型转换:(类型说明符)(表达式)
  1. double f=double(1)/double(2);

C类型转换的问题:

  • 任意类型之间都可以转换,编译器无法判断其正确性
  • 难于定位:在源码中无法快速定位

C++的类型转换

  • const cast:用于转换指针或引用,去掉类型的const属性(const变量即使内存被修改,读取的值不变,参考 const变量通过指针修改 详解 )。
  1. const int a = 10;
  2. //int* pA = &a; //类型不一致错误
  3. int* pA = const_cast<int*>(&a);
  4. *pA = 100;
  5. cout << a; //10,编译器只对const变量的值只读取一次
  • reinterpret_cast:重新解释类型(很危险),既不检查指向的内容,也不检查指针类型本身;但要求转换前后的类型所占用内存大小一致,否则将引发编译时错误。
  1. char* a = "a";
  2. void* b = a;
  3. char* c = reinterpret_cast<char*>(b);
  4. cout << c; //a
  • static_cast:用于基本类型转换,有继承关系类对象和类指针之间转换,由程序员来确保转换是安全的,它不会产生动态转换的类型安全检查的开销。
  1. int i = 6;
  2. double d = static_cast<double>(i); //基本类型转换 int -> double
  3. double d2 = 5.6;
  4. int i2 = static_cast<int>(d2); //基本类型转换 double -> int
  5. cout << d <<endl; //6
  6. cout << i2 << endl; //5
  • dynamic_cast:只能用于含有虚函数的类,必须用在多态体系中,用于类层次间的向上和向下转化;向下转化时,如果是非送的对于指针返回NULI。
  1. class Base
  2. {
  3. public:
  4. Base() : _i(0) { ; }
  5. virtual void T() { cout << "Base:T" << _i << endl; }
  6. private:
  7. int _i;
  8. };
  9. class Derived : public Base
  10. {
  11. public:
  12. Derived() :_j(1) { ; }
  13. virtual void T() { cout << "Derived:T" << _j << endl; }
  14. private:
  15. int _j;
  16. };
  17. int main()
  18. {
  19. Base cb;
  20. Derived cd;
  21. Base* pcb;
  22. Derived* pcd;
  23. // 子类--》 父类
  24. pcb = static_cast<Base*>(&cd);
  25. if (pcb == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; }
  26. pcb = dynamic_cast<Base*>(&cd);
  27. if (pcb == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; }
  28. // 父类--》 子类
  29. pcd = static_cast<Derived*>(&cb);
  30. if (pcd == NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; }
  31. pcd = dynamic_cast<Derived*>(&cb); //此处转换失败
  32. if (pcd== NULL) { cout << "unsafe dynamic_cast from Derived to Base" << endl; }
  33. return 0;
  34. }

适配器(Adapter)模式

适配器模式的定义参考 设计模式 | 适配器模式及典型应用

  • 适配器将类接口转换为客户端期望的另一个接口;
  • 使用适配器可防止类由于接口不兼容而一起工作;
  • 适配器模式的动机是,如果可以更改接口,则可以重用现有软件;

适配者类(被适配的角色,已存在的接口):

  1. class LegacyRectangle
  2. {
  3. public:
  4. LegacyRectangle(double x1, double y1, double x2, double y2)
  5. {
  6. _x1 = x1;
  7. _y1 = y1;
  8. _x2 = x2;
  9. _y2 = y2;
  10. }
  11. void LegacyDraw()
  12. {
  13. cout << "LegacyRectangle:: LegacyDraw()" << _x1 << " " << _y1 << " " << _x2 << " " << _y2 << endl;
  14. }
  15. private:
  16. double _x1;
  17. double _y1;
  18. double _x2;
  19. double _y2;
  20. };

目标抽象类(客户所需接口):

  1. class Rectangle
  2. {
  3. public:
  4. virtual void Draw(string str) = 0;
  5. };

第一种适配的方式——使用多重继承:

  1. class RectangleAdapter: public Rectangle, public LegacyRectangle
  2. {
  3. public:
  4. RectangleAdapter(double x, double y, double w, double h) :
  5. LegacyRectangle(x, y, x + w, y + h)
  6. {
  7. cout << "RectangleAdapter(int x, int y, int w, int h)" << endl;
  8. }
  9. virtual void Draw(string str)
  10. {
  11. cout << "RectangleAdapter::Draw()" << endl;
  12. LegacyDraw();
  13. }
  14. };

第二种适配的方式——组合方式的Adapter:

  1. class RectangleAdapter2 :public Rectangle
  2. {
  3. public:
  4. RectangleAdapter2(double x, double y, double w, double h) :
  5. _lRect(x, y, x + w, y + h)
  6. {
  7. cout << "RectangleAdapter2(int x, int y, int w, int h)" << endl;
  8. }
  9. virtual void Draw(string str)
  10. {
  11. cout << "RectangleAdapter2::Draw()" << endl;
  12. _lRect.LegacyDraw();
  13. }
  14. private:
  15. LegacyRectangle _lRect;
  16. };

使用适配器类:

  1. int main()
  2. {
  3. double x = 20.0, y = 50.0, w = 300.0, h = 200.0;
  4. RectangleAdapter ra(x, y, w, h);
  5. Rectangle* pR = &ra;
  6. pR->Draw("Testing Adapter");
  7. cout << endl;
  8. RectangleAdapter2 ra2(x, y, w, h);
  9. Rectangle* pR2 = &ra2;
  10. pR2->Draw("Testing2 Adapter");
  11. return 0;
  12. }

结果:

  1. RectangleAdapter(int x, int y, int w, int h)
  2. RectangleAdapter::Draw()
  3. LegacyRectangle:: LegacyDraw()20 50 320 250
  4. RectangleAdapter2(int x, int y, int w, int h)
  5. RectangleAdapter2::Draw()
  6. LegacyRectangle:: LegacyDraw()20 50 320 250

泛型编程的思想

  • 如果说面向对象是一种通过间接层来调用函数,以换取一种抽象,那么泛型编程则是更直接的抽象,它不会因为间接层而损失效率;

  • 不同于面向对象的动态期多态,泛型编程是一种静态期多态,通过编译器生成最直接的代码

  • 泛型编程可以将算法与特定类型、结构剥离,尽可能复用代码

模板函数

  1. // 模板函数
  2. template<class T>
  3. T max(T a, T b)
  4. {
  5. return a > b ? a:b;
  6. }
  7. //特化
  8. template<>
  9. char* max(char* a, char* b)
  10. {
  11. return (strcmp(a, b) > 0 ? (a) : (b));
  12. }
  13. template<class T1, class T2>
  14. int max(T1 a, T2 b)
  15. {
  16. return static_cast<int>(a > b ? a : b);
  17. }
  18. // 模板函数的测试
  19. cout << max(1, 2) << endl;
  20. cout << max(1.5, 3.5) << endl;
  21. cout << max('a', 'b') << endl; //b
  22. cout << max("hello", "world") << endl; //hello
  23. char* s1 = "hello";
  24. char* s2 = "world";
  25. cout << max(s1, s2) << endl; //world
  26. cout << max(10, 2.5) << endl; //10

模板类

  1. // 模板类
  2. template <class T>
  3. class TC
  4. {
  5. public:
  6. TC(T a, T b, T c);
  7. T Min();
  8. T Max();
  9. private:
  10. T _a, _b, _c;
  11. };
  12. template<class T>
  13. TC<T>::TC(T a, T b, T c):_a(a), _b(b), _c(c) { ; }
  14. template<class T>
  15. T TC<T>::Min()
  16. {
  17. T minab = _a < _b ? _a : _b;
  18. return minab < _c ? minab : _c;
  19. }
  20. template<class T>
  21. T TC<T>::Max()
  22. {
  23. T maxab = _a < _b ? _b : _a;
  24. return maxab < _c ? _c : maxab;
  25. }
  26. // 模板类的测试
  27. TC<int> obj1(2, 4, 3);
  28. cout << obj1.Min() << endl;
  29. cout << obj1.Max() << endl;
  30. TC<double> obj2(2.5, 4.4, 3.3);
  31. cout << obj2.Min() << endl;
  32. cout << obj2.Max() << endl;
  33. TC<long> obj3(399950L, 455795L, 333339090L);
  34. cout << obj3.Min() << endl;
  35. cout << obj3.Max() << endl;

泛型递归

计算1+2+3...+100的值,使用泛型递归可以在编译期间计算出值:

  1. // 1+2+3...+100 ==> n*(n+1)/2
  2. template<int n>
  3. struct Sum
  4. {
  5. enum Value {N = Sum<n-1>::N+n}; // Sum(n) = Sum(n-1)+n
  6. };
  7. template<>
  8. struct Sum<1>
  9. {
  10. enum Value {N = 1}; // n=1
  11. };
  12. int main()
  13. {
  14. cout << Sum<100>::N << endl;
  15. return 0;
  16. }

原文链接:http://www.cnblogs.com/timefiles/p/CppStudyNotesProgrammingThought.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号