目录
- 1.Any类型
- 1.说明
- 2.代码&使用
- 2.oneof类型
- 1.说明
- 2.代码&使用
- 3.map类型
- 1.说明
- 2.代码&使用
1.Any类型
1.说明
- 字段还可以声明为
Any
类型,可以理解为泛型类型- 使⽤时可以在
Any
中存储任意消息类型- 父类是
Message
- 父类是
Any
类型的字段也可以⽤repeated
来修饰
- 使⽤时可以在
Any
类型是Google已经定义好的类型,其中的include
⽬录下查找所有Google已经定义好的.proto
⽂件- 以我的机器为例:
ls /usr/include/google/protobuf
- 以我的机器为例:
2.代码&使用
.proto
文件syntax = "proto3"; package contacts;import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件message Address {string home_address = 1;string unit_address = 2; }message PeopleInfo {string name = 1;int32 age = 2;message Phone {string number = 1;enum PhoneType {MP = 0;TEL = 1;}PhoneType type = 2;}repeated Phone phone = 3;google.protobuf.Any data = 4; }message Contacts {repeated PeopleInfo contacts = 1; }
- 编译生成的CPP代码
// 新⽣成的 Address 类 class Address final : public ::PROTOBUF_NAMESPACE_ID::Message { public:using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;void CopyFrom(const Address& from);using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;void MergeFrom( const Address& from) {Address::MergeImpl(*this, from);}// string home_address = 1;void clear_home_address();const std::string& home_address() const;template <typename ArgT0 = const std::string&, typename... ArgT>void set_home_address(ArgT0&& arg0, ArgT... args);std::string* mutable_home_address();PROTOBUF_NODISCARD std::string* release_home_address();void set_allocated_home_address(std::string* home_address);// string unit_address = 2;void clear_unit_address();const std::string& unit_address() const;template <typename ArgT0 = const std::string&, typename... ArgT>void set_unit_address(ArgT0&& arg0, ArgT... args);std::string* mutable_unit_address();PROTOBUF_NODISCARD std::string* release_unit_address();void set_allocated_unit_address(std::string* unit_address); };// 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message { public:// .google.protobuf.Any data = 4;bool has_data() const;void clear_data();const ::PROTOBUF_NAMESPACE_ID::Any& data() const;PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Any* release_data();::PROTOBUF_NAMESPACE_ID::Any* mutable_data();void set_allocated_data(::PROTOBUF_NAMESPACE_ID::Any* data); };
- 上述代码中,对于
Any
字段- 设置和获取
- 获取⽅法的⽅法名称与字段命名完全相同
- 设置⽅法可以使⽤
mutable_
⽅法,返回值为Any
类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的内容进⾏修改
- 可以在
Any
字段中存储任意消息类型,这就要涉及到任意消息类型和Any
类型的互转PackFrom()
:将任意消息类型转为Any
类型UnpackTo
:将Any
类型转回之前设置的任意消息类型Is
:用来判断存放的消息类型是否为typename T
- 这部分代码就在 Google写好的⽂件
any.pb.h
中class PROTOBUF_EXPORT Any final : public ::PROTOBUF_NAMESPACE_ID::Message {bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) {...}bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const {...}template<typename T> bool Is() const {return _impl_._any_metadata_.Is<T>();} };
- 设置和获取
2.oneof类型
1.说明
- 如果消息中有很多可选字段, 并且将来同时只有⼀个字段会被设置
- 那么就可以使⽤
oneof
加强这个⾏为,也能有节约内存的效果
- 那么就可以使⽤
- 注意:
- 可选字段中的字段编号,不能与⾮可选字段的编号冲突
- 不能在
oneof
中使⽤repeated
字段 - 将来在设置
oneof
字段中值时,如果将oneof
中的字段设置多个,那么只会保留最后⼀次设置的成员,之前设置的oneof成员会⾃动清除
2.代码&使用
.proto
文件syntax = "proto3"; package contacts;import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件message Address {string home_address = 1;string unit_address = 2; }message PeopleInfo {string name = 1;int32 age = 2;message Phone {string number = 1;enum PhoneType {MP = 0;TEL = 1;}PhoneType type = 2;}repeated Phone phone = 3;google.protobuf.Any data = 4;// 其他联系⽅式:多选⼀oneof other_contact { string qq = 5; string weixin = 6;} }message Contacts {repeated PeopleInfo contacts = 1; }
- 编译生成的CPP代码
// 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message {enum OtherContactCase {kQq = 5,kWeixin = 6,OTHER_CONTACT_NOT_SET = 0,};// string qq = 5;bool has_qq() const;void clear_qq();const std::string& qq() const;template <typename ArgT0 = const std::string&, typename... ArgT>void set_qq(ArgT0&& arg0, ArgT... args);std::string* mutable_qq();PROTOBUF_NODISCARD std::string* release_qq();void set_allocated_qq(std::string* qq);// string weixin = 6;bool has_weixin() const;void clear_weixin();const std::string& weixin() const;template <typename ArgT0 = const std::string&, typename... ArgT>void set_weixin(ArgT0&& arg0, ArgT... args);std::string* mutable_weixin();PROTOBUF_NODISCARD std::string* release_weixin();void set_allocated_weixin(std::string* weixin);void clear_other_contact();OtherContactCase other_contact_case() const; };
- 上述的代码中,对于
oneof
字段- 会将
oneof
中的多个字段定义为一个枚举类型 - 设置和获取:
- 对
oneof
内的字段进⾏常规的设置和获取即可 - 但要注意只能设置⼀个,如果设置 多个,那么只会保留最后⼀次设置的成员
- 对
- 清空
oneof
字段:clear_
⽅法 - 获取当前设置了哪个字段:
_case
⽅法
- 会将
3.map类型
1.说明
- 语法⽀持创建⼀个关联映射字段,也就是可以使⽤
map
类型去声明字段类型,格式:map<key_type, value_type> map_field = N;
- 注意:
key_type
是除了float
和bytes
类型以外的任意标量类型value_type
可以是任意类型map
字段不可以⽤repeated
修饰- map 中存⼊的元素是⽆序的
2.代码&使用
.proto
文件syntax = "proto3"; package contacts;import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件message Address {string home_address = 1;string unit_address = 2; }message PeopleInfo {string name = 1;int32 age = 2;message Phone {string number = 1;enum PhoneType {MP = 0;TEL = 1;}PhoneType type = 2;}repeated Phone phone = 3;google.protobuf.Any data = 4;// 其他联系⽅式:多选⼀oneof other_contact {string qq = 5; string weixin = 6;}map<string, string> remark = 7; }message Contacts {repeated PeopleInfo contacts = 1; }
- 编译生成的CPP文件
// 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message {// map<string, string> remark = 7;int remark_size() const;void clear_remark();const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >& remark() const;::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >* mutable_remark(); };
- 上述的代码中,对于
Map
类型的字段- 清空map:
clear_
⽅法 - 设置和获取:
- 获取⽅法的⽅法名称与字段命名完全相同
- 设置⽅法为
mutable_
⽅法,返回值为Map
类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的0内容进⾏修改
- 清空map: