[C++][ProtoBuf][Proto3语法][二]详细讲解
DieSnowK 2024-07-16 12:35:01 阅读 80
目录
1.Any类型1.说明2.代码&使用
2.oneof类型1.说明2.代码&使用
3.map类型1.说明2.代码&使用
1.Any类型
1.说明
字段还可以声明为<code>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内容进⾏修改
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。