文章目录
- 2.3 oneof 字段
- 一、基本认识
- 二、 3.2 oneof相关函数
- 三、Contact2.3 改写
2.3 oneof 字段
本系列文章将通过对通讯录项目的不断完善,带大家由浅入深的学习Protobuf的使用。这是Contacts的2.3版本,在这篇文章中将带大家学习Protobuf的 oneof 语关键字,并将其用到我们的项目中
一、基本认识
oneof类型可以同时包含多个类型的字段,但是同时只能有一个字段被设置。在我们有多选一的需求时,oneof字段可强化这个行为,同时也能有节约内存的效果。
message PeopleInfo{
string name = 1;
// ……
oneof other_contact{
string qq = 5;
string wechat = 6;
}
}
oneof有如下的语法规定:
oneof内的字段和上一层的字段属于同一级别,因此不能重名
oneof内的字段不能用
Repeated
修饰oneof内同时只能有一个字段被设置。如果oneof字段被重复设置,则以最后设置的结果为准
二、 3.2 oneof相关函数
我们在 .proto 文件中添加“其他联系方式”字段,并使用oneof修饰
syntax = "proto3";
package contact2;
message Address{
string home = 1;
string company = 2;
}
message PeopleInfo{
string name = 1;
int32 age = 2;
message Phone{
string number = 1;
enum PhoneType{
MOBILE = 0;
FIXED = 1;
}
PhoneType type = 2;
}
repeated Phone phone = 3;
google.protobuf.Any addr = 4;
// ----------- 添加部分 ----------
oneof other_contact{
string qq = 5;
string wechat = 6;
}
// -------------------------------
}
message Contact{
repeated PeopleInfo contact = 1;
}
重新编译 .proto 文件后,观察学习新生成的代码
-
oneof字段被解释成枚举类型,内容如下:
enum OtherContactCase { kQq = 5, kWechat = 6, OTHER_CONTACT_NOT_SET = 0, };
-
对于qq,wechat字段,除了基本的设置、获取、清空等所有字段都会生成的函数外,还生成了
has_xx
函数,用来判断该字段是否被设置bool has_qq() const; bool has_wechat() const;
-
x_case()
函数用来判断oneof字段中哪一个字段被设置
三、Contact2.3 改写
write.cc
cout << "请选择其他联系方式:(0.NULL 1. QQ 2.wechat)";
int other;
cin >> other;
cin.ignore(256, '\n');
switch(other){
case 1:{
cout << "请输入联系人QQ号: ";
string QQ_number;
getline(cin, QQ_number);
p->set_qq(QQ_number);
break;
}
case 2:{
cout << "请输入联系人微信号: ";
string wechat_number;
getline(cin, wechat_number);
p->set_wechat(wechat_number);
break;
}
default:
break;
}
read.cc
// 方式一:用 has 方法判断字段是否被设置
if(people.has_qq()){
cout << "qq号: " << people.qq() << endl;
}else if(people.has_wechat()){
cout << "微信号: " << people.wechat() << endl;
}
// 方式二:使用 case 方法直接返回被设置的字段。扩展性更好
switch(people.other_contact_case()){
case contact2::PeopleInfo::OtherContactCase::kQq:{
cout << "qq号: " << people.qq() << endl;
break;
}
case contact2::PeopleInfo::OtherContactCase::kWechat:{
cout << "微信号: " << people.wechat() << endl;
break;
}
}