使用函数指针和多态代替冗长的if-else或者switch-case
在编程中,if-else和switch-case是很常见的分支结构,很少在程序中不用这些控制语句。但是不能否认,在一些场景下,由于分支结构过分长,导致代码不美观且不容易维护,在《重构》一书中,也将过长的switch语句当做了“坏味道”。例如当我们处理从网络接收到的数据时,往往会由于种类太多而写一长段的if-else或者switch-case,小弟就曾经在读别人处理网络数据的代码时,发现有50多条的if-else语句,导致函数代码非常长。因此小弟就在网上看各位高人的解决办法,有很多是支持使用if-else的,也有很多反对的,对于反对的,也有各种的解决方案,例如使用宏屏蔽if-else或者switch代码,使用函数指针列表等等。小弟在这里只介绍两种方法,一是使用函数指针列表,二是使用多态。
还希望各位大哥大姐,不惜赐教小弟其他的办法,多多交流。
1、函数指针列表,使用一个结构体将函数指针和一个标示指针的字符串封装起来,然后通过匹配相应的字符串,执行相应的函数。
测试代码:
- #include <stdio.h>
#include <string.h>
/*four functions for test*/
void functionA(int a);
void functionB(int b);
void functionC(int c);
void functionD(int d);
/*get the function by key and run it*/
void exec(const char* key,int value);
typedef void (*exceFunction)(int);
typedef struct mapFunction{
char* key;
exceFunction fun;
}mapFunction;
mapFunction map[4];
int main(void)
{
map[0].key = "a";
map[1].key = "b";
map[2].key = "c";
map[3].key = "d";
map[0].fun = &functionA;
map[1].fun = &functionB;
map[2].fun = &functionC;
map[3].fun = &functionD;
// test with changing the keys
exec("b",1);
return 0;
}
void exec(const char *key, int value){
int i=0;
for(;i<4;i++){
if(strcmp(key,map[i].key)==0){
map[i].fun(value);
break;
}
}
}
void functionA(int a)
{
printf("functionA:%d\n",a+1);
}
void functionB(int b)
{
printf("functionB:%d\n",b+2);
}
void functionC(int c)
{
printf("functionC:%d\n",c+3);
}
void functionD(int d)
{
printf("functionD:%d\n",d+4);
}
2、使用面向对象的多态机制,将实现不同功能的子类继承父类,然后重载父类的方法,在重载的方法中实现具体的功能。
主函数:
- #include <iostream>
#include <set>
#include <vector>
#include "test.h"
#include "testa.h"
#include "testb.h"
using namespace std;
std::vector<Test*> testVector;
void exec(const std::string key)
{
size_t i=0;
for(;i<testVector.size();i++){
Test* test = testVector.at(i);
if(test->getKey().compare(key)==0){
test->test();
break;
}
}
// do something
}
int main()
{
cout << "Hello World!" << endl;
testVector.push_back(new TestA("a"));
testVector.push_back(new TestB("b"));
exec("b");
return 0;
}
父类:
- #ifndef TEST_H
#define TEST_H
#include <string>
#include <iostream>
class Test
{
public:
Test(std::string key);
~Test();
const std::string getKey();
virtual void test(){}
private:
std::string key;
};
#endif // TEST_H
#include "test.h"
Test::Test(std::string key)
{
this->key = key;
}
Test::~Test()
{
this->key = "";
}
const std::string Test::getKey()
{
return this->key;
}
子类A:
- #ifndef TESTA_H
#define TESTA_H
#include <string.h>
#include <iostream>
#include "test.h"
class TestA : public Test
{
public:
TestA(std::string key);
void test();
};
#endif // TESTA_H
#include "testa.h"
TestA::TestA(std::string key):Test(key){}
void TestA::test(){
std::cout<<"TestA::test()";
}
子类B:
- #ifndef TESTB_H
#define TESTB_H
#include <string>
#include <iostream>
#include "test.h"
class TestB : public Test
{
public:
TestB(std::string key);
void test();
};
#endif // TESTB_H#include "testb.h"
TestB::TestB(std::string key):Test(key){}
void TestB::test()
{
std::cout<<"TestB::test()";
}
小弟才疏学浅,还请各位大神多多指教。
http://www.qtcn.org/bbs/apps.php?q=diary&a=detail&did=2030&uid=163485
使用函数指针和多态代替冗长的if-else或者switch-case的更多相关文章
- 2014 0416 word清楚项目黑点 输入矩阵 普通继承和虚继承 函数指针实现多态 强弱类型语言
1.word 如何清除项目黑点 选中文字区域,选择开始->样式->全部清除 2.公式编辑器输入矩阵 先输入方括号,接着选择格式->中间对齐,然后点下面红色框里的东西,组后输入数据 ...
- 关于函数指针与c++多态
原文 https://www.cnblogs.com/zhchngzng/p/4013031.html 虚函数是实现多态的重要元素,请看: class A { public: void a0(){c ...
- C 语言实现多态的原理:函数指针
C语言实现多态的原理:函数指针 何为函数指针?答案:C Programming Language. 能够查阅下,从原理上来讲,就是一个内存地址.跳过去运行相应的代码段. 既然如此,在运行时决定跳到哪个 ...
- C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)
//多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...
- 使用函数指针模拟C++多态
#include <iostream> using namespace std; class Base { public : void display() { cout << ...
- typedef 函数指针 数组 std::function
1.整型指针 typedef int* PINT;或typedef int *PINT; 2.结构体 typedef struct { double data;}DATA, *PDATA; //D ...
- [Reprint]C++普通函数指针与成员函数指针实例解析
这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下 C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...
- 类成员函数指针 ->*语法剖析
在cocos2d-x中,经常会出现这样的调用,如 ->*,这个是什么意思呢,如下面得这个例子: , 其实这是对类的成员函数指针的调用,在cocos2dx中,这种形式多用于回调函数的调用.如我们经 ...
- C++中怎么获取类的成员函数的函数指针?
用一个实际代码来说明. class A { public: staticvoid staticmember(){cout<<"static"<<endl;} ...
随机推荐
- GDOI2015——已成梦
今年GDOI(2015)在韶关北江中学(没记错的话应该是武江区)举行,感觉这五天就是一场梦,一场包含苦辣的梦. Day0 坐了一个上午的车,而且车内的空气又不好,感觉整个人都累倒下了. 到了北江之后吃 ...
- NDK Android* 应用移植方法
概述 本指南用于帮助开发者将现有的基于 ARM* 的 NDK 应用移植到 x86.假设您已经拥有一个正常执行的应用,须要知道怎样可以高速让 x86 设备在 Android* Market 中找到您的应 ...
- android中关于ListView的卡位说明
需求:做项目的时候,需要将ListView的header的一个Tab卡位,即listView滑动后,Header的某一个部分可以定在ListView的顶端卡住. 解决的方案:监听ListView的滑动 ...
- Spring mvc之提交表单
表单内容: <body> <form action="user/login"> <table> <tr> <td>用户名 ...
- JAVA中extends 与implements有啥区别?
JAVA中extends 与implements有啥区别?1. 在类的声明中,通过关键字extends来创建一个类的子类.一个类通过关键字implements声明自己使用一个或者多个接口.extend ...
- Java读写Word文件常用技术
Java操作操作Word文件,最近花了几天时间解决使用Word模板导出数据的问题,收集到一些资料分享下. 常见的技术如下: 1.POI(兼容doc.docx文件) 官方网站:http://poi. ...
- windows下安装mysql5.6.13的主从复制
如下操作均在vmware 虚拟机中winows xp 测试成功 中间走了很多弯路,网上的很多资料都是针对5.1以前的版本,在新版中根本无法使用,所以根据自己的实践整理了这篇文章 主服务:192.168 ...
- Linux下使用Mysql
一.连接MySQL数据库 一个最简单的程序示例: #include <stdio.h> #include "mysql.h" int main() { MYSQL my ...
- Unity 3D 文件导入出错
Unity 3D 文件导入出错 安装unity 时我选择了free版的,打开已有项目时出现例如以下错误提示 解决的方法: 先把要导入的文件先复制到unity3d安装文件夹下相应的文件夹内,之后再返回u ...
- 十天学习PHP之第三天
1)按右边的结构:查看改动表结构 2)按右边的浏览:查看表中的数据 3)按右边的SQL:执行SQL语句 4)按右边的插入:插入一行记录 5)按右边的清空:删除表中全部记录 6)按右边的删除: ...