1

我是一个为一台设备提供功能的工程库。该设备有一些共同的操作,但不同的算法来完成这些操作。我想要一个特定操作的函数原型,而不是一堆函数原型,而不是:

Alg1_Foo();
Alg2_Foo();
...

我要这个:

Foo(alg);

但是我不想将 alg 作为单独的参数传递,因为即使没有它,函数也会有很多参数,它们将具有用于识别和/或授权设备的参数,in 参数,out 参数(至少其中一个),所以我认为将 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. 删除命名空间(我们仍然可以在结构的帮助下模拟它们(这个线程可能对感兴趣的人有帮助:C 中的命名空间);

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

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

但是,虽然我不明白是否有可能通过维护 C 来完成我想做的事情......你看到了吗?或者将 alg_id 作为单独的参数传递而不打扰联合和结构是否更简单(但如果可能的话,我想避免它)?

4

1 回答 1

3

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

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

所以,是的,拆分你的职能,移除工会!

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

于 2013-03-01T23:43:49.863 回答