如何包含相同标题的两个不同版本?

时间:2013-07-10 13:26:56

标签: c++ header include version conflict

我正在将文件转换代码从专有文件格式编写为更通用的文件格式。我的目标是支持制造商文件格式的多个版本。

我有相同专有标头的多个版本。标题定义了构成主文件头的各种结构(文件只是一个大标题,后跟原始数据)。

我需要读取源文件的前4个字节来确定文件版本。反过来,文件版本告诉我使用哪个版本的C-structs来创建文件。

问题是:

  1. 我无法修改专有标题
  2. 标题不使用名称空间或类
  3. 标题中定义了一些很好的宏
  4. 可能的解决方案:

    • 为每个文件版本类型构建不同的转换器二进制文件:-(
      • 对用户和开发人员都不方便
    • 为每个版本动态加载库
      • 转换器是面向插件的,所以已经发生了很多这样的事情

    我尝试过使用命名空间进行黑客攻击:

    namespace version1 {
        #include "version1.h"
    }
    
    namespace version2 {
        #include "version2.h"
    }
    
    int main (void) {
        version1::header *hdr = new version1::header;
        return 0;
    }
    

    但是这不会起作用因为包含警戒,并且因为每个标题中都重新定义了多个宏。

    有没有一种优雅的方法来处理这个问题?

1 个答案:

答案 0 :(得分:5)

您可以使用两个不同的源文件以及前向声明:

// Forward declare in main.cpp:

namespace version1
{
   struct header;
}

namespace version2
{
   struct header;
}

// version1.cpp:

namespace version1
{
      #include <version1.h>
}

version1::header* new_v1_header()
{
   return new version1::header;
}

// other functions using `version1::header`

// version2.cpp:

namespace version2
{
      #include <version2.h>
}

version2::header* new_v2_header()
{
   return new version2::header;
}

// other functions using `version2::header`

另一种方法是实现一个包装类,它有一个只是空shell的基类:

class header_base
{
     virtual int func1(char *stuff) = 0; 
     ... many other virtual functions. 
};

// Create implementation of header_v1 or header_v2:
header_base* make_header(unsigned int magic);

header_base.cpp:

#include "header_v1.h"
#include "header_v2.h"

header_base* make_header(unsigned int magic)
{
    switch(magic)
    {
       case Magic_V1: 
          return new header_v1;
       case Magic_V2: 
          return new header_v2;
       default:
          assert(0);
          return 0;
    }
}

然后在两个单独的

中实现 在headerv1.h中

class header_v1 : public header_base
{
    int func1(char *stuff);
    ... 
};

header_v1.cpp:

#include "header1.h"

int header_v1::func1(char *stuff)
{
   ... 
   return 17;
}

类似于header_v2.h和header_v2.cpp。