non-virtual interface(NVI)手法:令用户通过public non-virtual成员函数间接调用private virtual函数,将这个non-virtual函数称为virtual函数的wrapper.wrapper确保得以在一个virtual函数被调用之前设定好适当场景,并在调用结束之后清理场景.注意此时用指针或引用调用该non-virtual成员函数时,该non-virtual成员函数调用的virtual函数取决于指针或引用的动态类型,即存在多态

  1. enum ShapeColor { Red, Green, Blue };
  2. class Shape
  3. {
  4. public:
  5. void draw(ShapeColor color = Red) const
  6. {
  7. doDraw(color);
  8. }
  9. private:
  10. virtual void doDraw(ShapeColor color) const = ;
  11. };
  12.  
  13. class Rectangle :public Shape
  14. {
  15. public:
  16.  
  17. private:
  18. virtual void doDraw(ShapeColor color) const;
  19. };
  20.  
  21. void Rectangle::doDraw(ShapeColor color) const
  22. {
  23. cout << "Rectangle's doDraw" << "color= " << color << endl;
  24. }
  25.  
  26. void main()
  27. {
  28. Shape*p = new Rectangle;
  29. ////输出:Rectangle's doDrawcolor= 0
  30. p->draw();
  31. system("pause");
  32. }

  1. enum ShapeColor { Red, Green, Blue };
  2. class Shape
  3. {
  4. public:
  5. void draw(ShapeColor color = Red)const
  6. {
  7. doDraw(color);
  8. }
  9. private:
  10. virtual void doDraw(ShapeColor color) const
  11. {
  12. cout << "Shape's doDraw" << "color= " << color << endl;
  13. }
  14. };
  15.  
  16. class Rectangle :public Shape
  17. {
  18. public:
  19.  
  20. private:
  21. virtual void doDraw(ShapeColor color) const;
  22. };
  23.  
  24. void Rectangle::doDraw(ShapeColor color) const
  25. {
  26. cout << "Rectangle's doDraw" << "color= " << color << endl;
  27. }
  28.  
  29. /*
  30. 输出:
  31. Shape's doDrawcolor= 0
  32. Rectangle's doDrawcolor= 0
  33. */
  34. void main()
  35. {
  36. Shape*p = new Shape;
  37. p->draw();
  38. delete p;
  39. p = NULL;
  40. Shape*q = new Rectangle;
  41. q->draw();
  42. delete q;
  43. q = NULL;
  44.  
  45. system("pause");
  46. }

  1. enum ShapeColor { Red, Green, Blue };
  2. class Shape
  3. {
  4. public:
  5.  
  6. void draw(ShapeColor color = Red)const
  7. {
  8. doDraw(color);
  9. }
  10. private:
  11. void doDraw(ShapeColor color) const
  12. {
  13. cout << "Shape's doDraw" << "color= " << color << endl;
  14. }
  15. };
  16.  
  17. class Rectangle :public Shape
  18. {
  19. public:
  20.  
  21. private:
  22. void doDraw(ShapeColor color) const;
  23. };
  24.  
  25. void Rectangle::doDraw(ShapeColor color) const
  26. {
  27. cout << "Rectangle's doDraw" << "color= " << color << endl;
  28. }
  29. /*
  30. 输出:
  31. Shape's doDrawcolor= 0
  32. Shape's doDrawcolor= 0
  33. */
  34. int main()
  35. {
  36. Shape*p = new Shape;
  37. p->draw();
  38. delete p;
  39. p = NULL;
  40. Shape*q = new Rectangle;
  41. q->draw();
  42. delete q;
  43. q = NULL;
  44.  
  45. system("pause");
  46. return ;
  47. }

c++之NVI手法的更多相关文章

  1. Effective C++ -----条款35:考虑virtual函数以外的其他选择

    virtual函数的替代方案包括NVI手法及Strategy设计模式的多种手法.NVI手法自身是一个特殊形式的Template Method设计模式. 将机能从成员函数移到class外部函数,带来的一 ...

  2. Effective C++ 的55个条款

    看完Effective C++才觉得平时程序设计时需要注意的一些问题,有一定的收获,不过因为没什么项目实践, 并未很深入了解具体情况如何,还需后继实践~ 列举一下55个条款: 1. 视C++为一个语言 ...

  3. 考虑virtual函数以外的其它选择

    详情见<Effective C++>item35 1.使用non-virtual interface(NVI)手法,这是Template Method设计模式的一种特殊形式. 它以publ ...

  4. Effective C++ 总结(三)

    五.实现  条款26:尽可能延后变量定义式的出现时间 如果你定义了一个变量且该类型带一个构造函数或析构函数,当程序到达该变量时,你要承受构造成本,而离开作用域时,你要承受析构成本.为了减少这个成本,最 ...

  5. Effective C++:条款35:考虑virtual函数以外的其它选择

    游戏中的人物伤害值计算问题. (一)方法(1):一般来讲能够使用虚函数的方法: class GameCharacter { public: virtual int healthValue() cons ...

  6. Effective C++笔记 55条编程法则

    1.  视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 2.  尽量以const,enum.inline替代#define 1) 对于单纯常量,最好以const ...

  7. EC读书笔记系列之16:条款35、36、37、38、39、40

    条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...

  8. Effective C++:条款37:绝不又一次定义继承而来的缺省參数值

    因为又一次定义继承而来的non-virtual函数是不对的(见上一个条款),所以这个条款就将问题局限于:绝不又一次定义继承一个带有缺省參数值的virtual函数. (一) virtual函数是动态绑定 ...

  9. EffectiveC++ 第6章 继承与面向对象设计

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 6 继承与面向对象设计 Inheritance and ...

随机推荐

  1. 常用的-->查找算法与排序算法

    顺序查找 从列表第一个元素开始,顺序进行搜索,直到找到为止. 二分查找 从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半. li = [1, 2, ...

  2. Unexpected Exception caught setting 'username' on 'class com.bj186.crm.web.action.UserAction: Error setting expression 'username' with value ['艾格尼丝', ]

    问题场景: 在使用表单向Action传递数据的时候, 遇到了这个问题, 导致了空指针异常. 问题描述: 10:14:56.622 [http-nio-8080-exec-45] ERROR com.o ...

  3. 【php】查看扩展的版本

    php --ri [扩展名称] 例如: php --ri mongodb mongodb MongoDB support => enabled MongoDB extension version ...

  4. lspci详解分析

    lspci详解分析 一.PCI简介 PCI是一种外设总线规范.我们先来看一下什么是总线:总线是一种传输信号的路径或信道.典型情况是,总线是连接于一个或多个导体的电气连线,总 线上连接的所有设备可在同一 ...

  5. oracle 存储过程,存储函数,包,

    http://heisetoufa.iteye.com/blog/366957 认识存储过程和函数 存储过程和函数也是一种PL/SQL块,是存入数据库的PL/SQL块.但存储过程和函数不同于已经介绍过 ...

  6. PyTorch的十七个损失函数

    本文截取自<PyTorch 模型训练实用教程>,获取全文pdf请点击: tensor-yu/PyTorch_Tutorial​github.com 版权声明:本文为博主原创文章,转载请附上 ...

  7. [LOJ] 分块九题 4

    https://loj.ac/problem/6280 区间修改,区间求和. 本来线段树的活. //Stay foolish,stay hungry,stay young,stay simple #i ...

  8. thinkphp5实现文件上传

    原理:通过form表单的enctype = "multipart / form-data"属性将文件临时放在htdocs文件夹的tmp目录下,再通过后台的程序将文件保存在自己设定的 ...

  9. Linux硬盘的检测--smartctl详细介绍

    概述  随着硬盘容量.速度的快速发展,硬盘的可靠性问题越来越重要,今天的单块硬盘存储容量可轻松达到1TB,硬盘损坏带来的影响非常巨大.不同的文件系统(xfs,reiserfs,ext3)都有自己的检测 ...

  10. idea 设置系列 各种乱码

    http://blog.csdn.net/u013361445/article/details/51113692 把idea设置的好,才能用的好.