protobuf2.7.0在RedHat6.4下编译问题

 1、问题说明    

      项目中多个应用有跨语言跨平台的信息交互需求,因此选择了protobuf做协议编解码。在github上下载了2.7.0版本,根据安装说明编译后,编译失败,报如下错误:

./google/protobuf/metadata.h: In constructor ‘google::protobuf::internal::InternalMetadataWithArena::InternalMetadataWithArena(google::protobuf::Arena*)’:
./google/protobuf/metadata.h:174: 错误:类‘google::protobuf::internal::InternalMetadataWithArena’没有名为‘InternalMetadataWithArenaBase’的字段
./google/protobuf/metadata.h: In constructor ‘google::protobuf::internal::InternalMetadataWithArenaLite::InternalMetadataWithArenaLite(google::protobuf::Arena*)’:
./google/protobuf/metadata.h:203: 错误:类‘google::protobuf::internal::InternalMetadataWithArenaLite’没有名为‘InternalMetadataWithArenaBase’的字段

      打开metadata.h文件查看后发现文件中定义了三个类,一个基类,两个派生类,如下所示(两派生类派生于同一基类,此处只选了一个):

template 
class InternalMetadataWithArenaBase {
public:
  InternalMetadataWithArenaBase() : ptr_(NULL) {}
  explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {}

  ~InternalMetadataWithArenaBase() {
    if (have_unknown_fields() && arena() == NULL) {
      delete PtrValue();
    }
    ptr_ = NULL;
  }
  //省略...
};

class InternalMetadataWithArena : 
          public InternalMetadataWithArenaBase {
public:
  InternalMetadataWithArena() {}
  explicit InternalMetadataWithArena(Arena* arena) :
      InternalMetadataWithArenaBase(arena) {}          // !!!! error  !!!!


  void DoSwap(UnknownFieldSet* other) {
    mutable_unknown_fields()->Swap(other);
  }
  //省略...
};

2、解决方案        

        查看编译错误信息,可以发现错误定位在派生类中由explicit修饰的构造函数处,编译器识别不出来初始化列表中用于初始化基类构造函数的符号。因此,可以从基类定义以及派生类对基类的使用两方面来查找错误原因。

        该文件中,三个类的关系是两个普通类继承一个模板基类,而基类定义本身并无问题,就只能看使用了。由于派生类已经指明了模板参数,在派生类中引用模板基类,必须指明模板参数,否则编译器无法正确生成模板类的实例。将派生类红字处修改为如下形式后,编译通过。

        附加说明:用explicit修饰单参数的构造函数,是为了告诉编译器该构造函数是显示的,不能利用它进行隐式的类型转换。

//...省略
  explicit InternalMetadataWithArena(Arena* arena) :
      InternalMetadataWithArenaBase(arena) {}  // !!!! OK  !!!!
//...省略

3、编译环境

       谷歌上传到github上的代码应该是经过测试的,所以推测是编译器的问题,可能使用高版本的编译器并无错误。
       我这里的编译环境如下:
操作系统:RedHat 6.4 x86_64位(内核Linux data8 2.6.32-358.el6.x86_64)
GCC:gcc 版本 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC)
       没有在更高版本的gcc上试过,可能模板语法在新版本的C++中已经有所变化吧,感兴趣的可以试试。


你可能感兴趣的:(linux开发)