背景
#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