我正在编写一个调用底层C函数的现有C ++代码。当前的代码已经正常工作但我要做的是传递一些新的参数并使用这些新的参数来修改一些行为。下面的代码证明了这个想法:
// this is how the existing works look like without my changes:
do_something_case1(int p1, double p2, struct1* p3, ...)
{
... // do a lot of things
// my work is to give client ability to override config1, config2
// with their own structures.
// get_config1() and get_config2() are existing pre-defined
// configurations and are used extensively elsewhere.
ConfigStruct1 config1 = get_config1(...);
... // do a lot of things
ConfigStruct2 config2 = get_config2(...);
... // do something
foo(config1, config2, ...);
... // more code
}
do_something_case2(int p1, double p2, struct1* p3, ...)
{
// in a similar situation as do_something_case1
}
... // more do_something_case3, do_something_case4 defined here
// this function needs to take client overrides.
void do_something(int p1, double p2, struct1* p3, ...)
{
if(case1)
{
do_something_case1(p1, p2, p3, ...);
}
else if(case2)
{
do_something_case2(p1, p2, p3, ...);
}
else if(case3)
{
do_something_case3(p1, ...);
}
else if(...) // more if statements to come
{
... // do something
}
}
我的工作是让客户端能够使用自己的ConfigStruct。在ConfigStruct1的主要内容中,ConfigStruct2应该是输入,而不是在函数中决定,它不会给客户端很大的自由来覆盖它们。但是这些代码非常陈旧,并且在系统中广泛使用,我不想破坏任何现有的客户端代码。我绝对想利用已经在这些do_something_case()函数中定义的所有其他复杂逻辑。如果这是C ++,我可以简单地添加一个带有默认值的新参数
// if it were C++, I could do:
do_something_case1(int p1, double p2, struct1* p3, ...,
ConfigStruct1* pConfig1=NULL,
ConfigStruct2* pConfig2=NULL)
{
if(NULL == pConfig1)
{
// call get_config1(..)
}
}
或使用函数重载。但由于C也不支持,我觉得我被困在更少和更丑陋的选项上。解决问题的一种方法是复制并粘贴所有这些功能,并在新功能中进行手术更改。这将使它更加丑陋。你有什么建议可以帮我解决问题吗?
非常感谢你。
答案 0 :(得分:1)
如果这是C ++,我可以简单地添加一个采用默认值的新参数
只有您愿意并且能够重新编译使用此功能的所有。听起来这可能是一个很大的麻烦,甚至可能都不可行。还有更多的烟雾和更多C ++中的镜像比实际的魔法还要多。
[...]或使用函数重载。
C ++重载函数被提前绑定 - 或者至少,在编译时选择在任何特定调用中使用的特定重载签名。因此,简单地添加重载版本将不足以使现有代码调用新版本。相反,您需要重新编译所有内容。烟,镜子,没有魔力。
对于C语言中的解决方案,更改do_something_case()
函数的参数数量几乎不是首发。这不仅需要您重新编译所有内容,还需要您修改每个调用。您可以利用C预处理器来自动执行其中的一些操作,但它仍然会很混乱。
看起来get_config1()
和get_config2()
函数可能是可行的扩展点,但是,假设它们返回指针而不是问题中描述的实际结构。这假定客户端结构将符合预期的配置结构类型,最后添加,这似乎无论如何都需要do_something_case()
调用的函数才能工作。您可以修改get_config()
函数,但效果最好,或者可能建立一种机制,通过策略使用动态链接器,客户端可以通过该机制提供自己的实现。