c++基于模板元简化if else模式编码

本文探讨了C++中由于大量if-else导致的代码维护问题,并提出了两种解决方案:1) 使用键-计算函数映射,部分解决了问题;2) 利用模板元编程和类型列表,通过编译器自动生成if-else逻辑,自动检查所有类型组合,降低了维护成本和错误概率。同时,文章指出该方法可能会增加编译时间。

背景

#include <iostream>

class Base
{
  public:
    virtual ~Base() {}
};

class Derived1: public Base{};
class Derived2: public Base{};

class Executor
{
  public:

    void caculate(Derived1* trimed, Derived2* circle)
    {
      // use other parameters
      std::cout << "Derived1 dist Derived2" << std::endl;
    }
    void caculate(Derived2* circle, Derived1* trimed)
    {
      // use other parameters
      std::cout << "Derived2 dist Derived1" << std::endl;
    }
    void caculate(Derived1* lineSegment, Derived1* trimed)
    {
      // use other parameters
      std::cout << "Derived1 dist Derived1" << std::endl;
    }
    void caculate(Derived2* circle, Derived2* trimed)
    {
      // use other parameters
      std::cout << "Derived2 dist Derived2" << std::endl;
    }

    void caculateAll(Base* curve1, Base* curve2)
    {
      if(auto base1 = dynamic_cast<Derived2*>(curve1))
      {
        if (auto base2 = dynamic_cast<Derived2*>(curve2))

          caculate(base1, base2);
      }
      else if (auto base2 = dynamic_cast<Derived1*>(curve2))
      {
        caculate(base1, base2);
      }
    }
    else if(auto base1 = dynamic_cast<Derived1*>(curve1))
    {
      if (auto base2 = dynamic_cast<Derived2*>(curve2))
      {
        caculate(base1, base2);
      }
      else if (auto base2 = dynamic_cast<Derived1*>(curve2))
      {
        caculate(base1, base2);
      }
    }
}

关注Executor::caculateAll函数,有以下问题:

1,如果当Base派生的子类越来越多时,if else会爆增,难以维护,不停的在同一个函数内添加修改代码,出错概率增加,违反了开闭原则

2,if语句先后顺序对程序正确性可能有影响,比如 Dev2 从Dev1 继承,Dev1从Base继承,那么dynamic case需要从Dev2开始测试然后Dev1,因为Dev2始终是可以cast成Dev1的,顺序出错,选择函数将有问题

3,如此庞大的组合,有可能忘记某个组合,N*N组合,如果是3个类型N*N*N,可能忘记某一个

解决方案一:

采用了key → caculate函数的方案,使用动态类型1的字符+动态类型2字符作为key 映射到 一个函数,此方案缓解了1中的问题,完美的解决了2中的问题,没有解决3中的问题

解决方案二

先贴出完整代码:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <filesystem>

class PSGMCurve
{
public:
    virtual ~PSGMCurve() {}
};
 
class PSGMCurveCircle : public PSGMCurve{};
class PSGMCurveTrimmed : public PSGMCurve{};
class PSGMCurvePlane : public PSGMCurveTrimmed{};
class PSGMCurveZlh : public PSGMCurve{};

struct PSGMNullType{}; //引入空类型
 
//引入typelist
template <class T, class U>
struct PSGMTypeList
{
    typedef T Head;
    typedef U Tail;
};
//这里为了方便阅读只定义到长度3,这个如果要增加简单的copy几次,就可以达到几十个,而且这个只需要定义一次
#define PSGM_TYPELIST_1(T1) PSGMTypeList<T1, PSGMNullType>
 
#define PSGM_TYPELIST_2(T1, T2) PSGMTypeList<T1, PSGM_TYPELIST_1(T2)>
 
#define PSGM_TYPELIST_3(T1, T2, T3) PSGMTypeList<T1, PSGM_TYPELIST_2(T2, T3)>

#define PSGM_TYPELIST_4(T1, T2, T3, T4) PSGMTypeList<T1, PSGM_TYPELIST_2(T2, T3, T4)>

class PSGMExecutor
{
public:
 
    void caculate(PSGMCurveTrimmed* trimed, PSGMCurveCircle* circle)
    {
        // use other parameters
        std::cout << "PSGMCurveTrimmed dist PSGMCurveCircle" << std::endl;
    }
    void caculate(PSGMCurveCircle* circle, PSGMCurveTrimmed* trimed)
    {
        // use other parameters
        std::cout << "PSGMCurveCircle dist PSGMCurveTrimmed" << std::endl;
    }
    void caculate(PSGMCurveTrimmed* lineSegment, PSGMCurveTrimmed* trimed)
    {
        // use other parameters
        std::cout << "PSGMCurveTrimmed dist PSGMCurveTrimmed" << std::endl;
    }
    void caculate(PSGMCurveCircle* circle, PSGMCurveCircle* trimed)
    {
        // use other parameters
        std::cout << "PSGMCurveCircle dist PSGMCurveCircle" << std::endl;
    }

    void caculate(PSGMCurveTrimmed* circle, PSGMCurvePlane* trimed)
    {
        // use other parameters
        std::cout << "PSGMCurveTrimmed dist PSGMCurvePlane" << std::endl;
    }

    void caculate(PSGMCurvePlane* trimed, PSGMCurveTrimmed* circle)
    {
        // use other parameters
        std::cout << "PSGMCurvePlane dist PSGMCurveTrimmed" << std::endl;
    }

    void caculate(PSGMCurvePlane* obj1, PSGMCurvePlane* obj2)
    {
        // use other parameters
        std::cout << "PSGMCurvePlane dist PSGMCurvePlane" << st
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值