c \ c ++ - 具有联合作为参数以满足特定要求的函数

时间:2013-03-01 23:23:55

标签: c++ c arguments compatibility unions

我正在设计库来为一台设备提供功能。该设备具有一些常用操作,但具有不同的算法来完成这些操作。我想要一个特定操作的一个函数原型,而不是一堆它们,而不是:

Alg1_Foo();
Alg2_Foo();
...

我想要这个:

Foo(alg);

但是我不想将alg作为单独的参数传递,因为即使没有它,函数也会有很多参数,它们将有参数用于识别和/或授权设备,参数,参数(至少其中之一),所以我认为将alg添加为单独的参数会很烦人。

所以我的想法是提供像这样的解决方案:

Foo(const SomeUnion& some_union);

其中:

union SomeUnion {
  AlgId alg_id;
  alg1::SomeStruct alg1_some_struct;
  alg2::SomeStruct alg2_some_struct;

  SomeUnion(alg1::SomeStruct some_struct) { alg1_some_struct = some_struct; };
  SomeUnion(alg2::SomeStruct some_struct) { alg2_some_struct = some_struct; };
};

特定算法的结构如下:

namespace alg1 {
  struct SomeStruct {
    static const AlgId alg_id = ALG1;
    . . .
  };
}

因此,如果想要执行alg1,我们将适当的结构传递给Foo并且它在C ++中工作,比如说

alg1::SomeStruct a;
Foo(a);

但我希望我的图书馆能够保持纯C的可能性。当然,我需要:

  1. 删除引用并用指针替换它们;

  2. 删除命名空间(我们仍然可以在结构的帮助下模拟它们(这个帖子可能对那些感兴趣的人有用:Namespaces in C);

  3. 替换C ++ - 从C定义结构的样式,并在标记名称空间中定义名称(typedef struct tagStruct {...} Struct;);

  4. 从内部结构和联合中删除函数。

  5. 但是我无法理解是否有可能完成我想要做的维护C ...你看到了方法吗?或者将alg_id作为一个单独的参数传递而不是为了打扰工会和结构只是更简单(但我想尽可能避免它)?

1 个答案:

答案 0 :(得分:3)

对我来说,这似乎是一个典型的案例,有人试图以“错误的方式”解决问题。

如果你有一个函数的“很多参数”,那么使用struct就可以了。但是在struct内隐藏“你实际上正在调用哪个函数”,然后在struct内部有union的几个变体,现在我们试图在一个函数中填充太多。开始分割函数,只需要一个struct - 删除你的union作为参数 - 这是错误的。 [我使用的代码与此类似的东西 - 潜入一些代码执行错误操作并导致一些难以找到错误的机会,因为你将错误类型的union参数传递给函数使得这个真是个糟糕的解决方案]。如果将错误类型的结构传递给普通函数,编译器会告诉您。如果你填写了一个联合的错误部分,使用结构的“右”部分的代码将得到“奇怪的”数据[很可能是未定义的行为] - 这种类型的错误很难找到。

是的,分开你的功能,删除联盟!

修改 如果您希望拥有一个简单且一致的接口,那么您会想到一个建议:您有一个工厂函数,它将alg_id传递给它,它返回一个指向相关函数的函数指针。不幸的是,如果每个函数的接口都是我建议的,不同的结构,那么你仍然有可能混淆数据结构和函数,但它确实减少了“已​​发布函数”的数量 - 事实上,这些函数不需要在提供它们的模块[库甚至对象文件]之外都可见。