如何在C中定义两个实现?

时间:2014-09-06 22:21:16

标签: c

我希望有两个实现A.h A.c和B.h B.c 他们声明了相同的方法,唯一的区别是.c文件中的实现。

但是现在我的重复符号出现了链接错误。

1 个答案:

答案 0 :(得分:2)

更改名称。

没有"命名空间"在C.他们被添加到C ++。在C中,全局范围内的所有内容都必须具有唯一的名称。

所以给你的东西添加前缀

A_Function1
A_Function2

B_Function1
B_Function2

如果你只需要1个实现(比如一个用于Mac而另一个用于Windows),那么当然只链接一个或使用#if关闭一个

// a.h
#if USE_A
...
#endif  // USA_A

// a.c
#if USE_A
...
#endif  // USE_A

对于B.然后在编译时可以使用

cc -DUSE_A=1

否则,如果你需要在运行时切换实现(比如OpenGL vs DirectX后端),这通常是用函数指针完成的。

你制作了另一个带有函数指针的文件。然后使用实现A或B中的任一函数填充那些指向函数的指针。所有其他文件仅引用函数指针。

// a.h
int A_SomeFunc(int arg1);

// a.c
#include "a.h"
int A_SomeFunc(int arg1) {
  ...
}

// b.h
int B_SomeFunc(int arg1);

// b.c
#include "b.h"
int B_SomeFunc(int arg1) {
  ...
}

// virtual.h
extern int (*SomeFunc)(int arg1); 

void Init(int implementation) // 0 = A, 1 = B

// virtual.c
#include "a.h"
#include "b.h"

int (*SomeFunc)(int arg1);

void Init(int implementation) {
  switch (implementation) {
    case 0: // use A
      SomeFunc = A_SomeFunc;
      break;
    case 1: // use B;
      SomeFunc = B_SomeFunc;
      break;
  }
}

现在,在程序开始的某个地方,您需要致电Init。然后其他文件可以包含virtual.h,并将使用您在Init中选择的任何实现。

要将其提升到新的水平,请将SomeFunc放入结构中。

struct SomeAPI {
 int (*SomeFunc)(int arg1);
};

现在更改Init以填写SomeAPI

void Init(struct SomeAPI* someAPI, int implementation) {
  switch (implementation) {
    case 0: // use A
      someAPI->SomeFunc = A_SomeFunc;
      break;
    case 1: // use B;
      someAPI->SomeFunc = B_SomeFunc;
      break;
  }
}

现在,您已经有效地制作了C ++类的虚函数。其他模块会做类似

的事情
struct SomeAPI api;
Init(&api, 1);  // choose B
int result = api.SomeFunc(someIntArgument);

或者

struct SomeAPI* pAPI = malloc(sizeof(SomeAPI));
Init(pAPI, 1); // choose B
int result = api->SomeFunc(someIntArgument);