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

文章目录

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

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

【Protobuf速成指南】oneof类型的使用_第1张图片

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

【Protobuf速成指南】oneof类型的使用_第2张图片


【Protobuf速成指南】oneof类型的使用_第3张图片

你可能感兴趣的:(【Protobuf速成教程】,Protobuf,C++)