【Protobuf速成指南】oneof类型的使用

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有如下的语法规定:

  1. oneof内的字段和上一层的字段属于同一级别,因此不能重名

  2. oneof内的字段不能用 Repeated 修饰

  3. 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字段中哪一个字段被设置

    image-20230611090859623

三、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;
}

image-20230611092859657

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;
    }
}

image-20230611092949747


在这里插入图片描述

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罅隙`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值