[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是除了floatbytes类型以外的任意标量类型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内容进⾏修改




声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。