文章目录
- 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;}
}