C++类功能扩展预留五招
第一招虚函数
通过派生类来进行功能扩展是基本的面向对象的方式,这种方式大如下:
class base
{
public:
virtual ~base(){}
virtual void fun()
{
cout << "基本功能" << endl;
}
};
class derive:public base
{
public:
void fun()
{
cout << "扩展功能" << endl;
}
};
这种方式下,基类通过声明虚函数,让派生类来覆盖,最后通过多态来实现扩展功能。这种方式的最大的缺点是基类的编写者一般很难确定虚函数的功能究竟要实现到什么程度,如果有一天突然发现一个虚函数的功能要进行扩张(或收缩),那么所有从这个基类派生的类都要进行编译。这种方式的另一个缺憾是。功能的扩展不能在运行时设定。
第二招组合
通过组合方式来为类的功能扩展留下余地的方式,要比通过继承的方式在耦合方面要松的多。就是把上面的虚函数所要委托给一个其它的类。这种方式大体如下:
class action
{
public:
virtual void fun()
{
cout << "基本功能" << endl;
}
};
class exAction:public action
{
public:
virtual void fun()
{
cout << "扩展功能" << endl;
}
};
class app
{
public:
app():paction(NULL){}
virtual ~app(){}
virtual void fun()
{
if(paction)
paction->fun();
}
void setActoin( action* action_)
{
paction = action_;
}
private:
action* paction;
};
在这个例子中,类app把它的功能委托给了类action。这样一来,类app就和它的功能进行了解藕。解藕后的类app现在可以在运行时进行功能设定了。通过组合的方式虽然解藕了也能进行功能的运行时设定了。但却明显地不如第一种方式效率高。
第三招函数指针成员
通过函数指针成员方式,可以提高效率。这种方式大体如下:
class app
{
public:
app():pfun(NULL){}
virtual ~app(){}
typedef void(*FUN)();
void setFun(FUN fun_)
{
pfun = fun_;
}
virtual void fun()
{
if( pfun)
pfun();
}
private:
FUN pfun;
};
第四招成员模板函数
通过为类预留一个成员模板函数,而为类的使用者留下扩展的余地。这种方式简捷、干练。遗憾的是这种方式不能用在动态方面上。这种方式大体如下:
class app
{
public:
app(){}
virtual ~app(){}
template <class T>
void fun( T& t_)
{
cout << "基本功能" << endl;
}
};
template < >
void app::fun(int & t_)
{
cout << "扩展功能" << endl;
}
这种方式还能依偏特化的形式进行,具体请参考我的另一篇blog《让后门能够偏特化》。使用这种方式最奇妙的是声明一个模板构造函数来扩展类的构造功能。
第五招模板基类
上面的几种方式都是针对一个要进行开发的类为这个要开发的类留下扩展余地。那么能不能让要开发的类用来扩展任意的已开发好的类的功能呢?这就是第五招模板基类。这种方式大体如下:
template < class T>
class exApp:public T
{
public:
void fun()
{
cout << "扩展功能" << endl;
}
};
现在我们可以方便的把类exApp的功能添加到任意的其它的类上了。这种扩展方式的功能非常强悍,它甚至引出一个专门的编程方式:“基于策略的编程”。
详见《C++程序设计就思维》。
原文转自:http://blog.csdn.net/guanwl/article/details/2358073
原作者为 guanwl。请尊重原作者版权
C++类功能扩展预留五招的更多相关文章
- 利用Mixins扩展类功能
8.18 利用Mixins扩展类功能 - python3-cookbook 3.0.0 文档 https://python3-cookbook.readthedocs.io/zh_CN/latest/ ...
- [转]用GSON 五招之内搞定任何JSON数组
关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 <Google Gson的使用方法,实现Json结构的相互转换> ,写的很好,通俗易懂. 我为什么写这篇文章呢?因为前几晚跟 ...
- [转] Android:用GSON 五招之内搞定任何JSON数组
[From] http://www.open-open.com/lib/view/open1472632967912.html 写在前面 关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展
一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...
- IOS基础之 (十二) 类的扩展
对OC类的扩展总结如下,共有4个: 1.子类 subClass 作用:可以使用类的继承来增添父类的变量和方法. 写法:在.h文件中 @interface Student : Person 2.分类 C ...
- spring源码深度解析-2功能扩展
容器功能的扩展ApplicationContext用于扩展BeanFactory中现有的功能.究竟多出了哪些功能,进一步探索.写法上:BeanFactory bf = new XmlBeanFacto ...
- vs.net 2013 Saffolding功能扩展
vs.net 2013 Saffolding功能扩展 Asp.net mvc 5 CRUD代码自动生成工具 -Visual Studio.net2013 Saffolding功能扩展 上次做过一个&l ...
- Asp.net mvc 5 CRUD代码自动生成工具- vs.net 2013 Saffolding功能扩展
Asp.net mvc 5 CRUD代码自动生成工具 -Visual Studio.net2013 Saffolding功能扩展 上次做过一个<Asp.net webform scaffoldi ...
随机推荐
- linux rpm 安装和卸载
[root@wang Packages]# mount /dev/cdrom /mnt 挂载 [root@wang Packages]# rpm -ivh zip-3.0-1.el6.x86_64.r ...
- VS2010最常用快捷键
1.选择类 F8 当前位置变成选定区域的头/尾(再移动光标或者点鼠标就会选定) Ctrl + F8 当前行变成选定区域的头/尾(再移动上下光标或者点鼠标就会选定多行) CTRL + W 选择当前单词 ...
- [书目20160624]Android应用开发从入门到精通
卢海东 著 第1章 揭开神秘面纱——Android系统简介 1 1.1 认识Android系统 2 1.1.1 Android成长历程 2 1.1.2 发行版本 3 1.1.3 得到大 ...
- document对象补充
五.相关元素操作: var a = document.getElementById("id"); 找到a: var b = a.nextSibling ...
- LESS速查
注释 缓存式注释/*注释内容*/ 非缓存式注释//注释内容 变量 @nice-blue: #5B83AD; @light-blue: @nice-blue + #111; #header { col ...
- java 24 - 11 GUI之制作登陆注册页面
简单说说,懒得发了... 步骤: A:首先写出登陆注册需要用到类以及代码(IO流) B:然后创建登陆窗口和注册窗口 C:各个监听事件: a:登录窗口 1.重置:把2个文本框的内容全部清空 2.注册:关 ...
- 转: Eclipse 分屏显示同一个文件
Eclipse 分屏显示同一个文件 场景 : 某个类很大,可能有数千行.当你想要将类开头部分与中间或者靠后的部分进行对比时,请follow如下步骤: Window -> Editor -&g ...
- HTML 学习笔记 JavaScript (DOM)
一 DOM 简介 通过HTML DOM 可以访问JavaScript 文档的所有元素 当网页被加载的时候,浏览器会创建页面的文档对象模型 HTML DOM 模型被构造成对象的树 HTML DOM 树 ...
- angularjs之$timeout指令
angular.js的$timeout指令对window.setTimeout做了一个封装,它的返回值是一个promise对象.当定义的时间到了以后,这个promise对象就会被resolve,回调函 ...
- Distribute numbers to two “containers” and minimize their difference of sum
it can be solved by Dynamical Programming.Here are some useful link: Tutorial and Code: http://www.c ...