介绍C++中gRPC访问结构体成员的方式和const成员函数访问时的限制。
当gRPC proto协议中定义的message消息不仅仅包含基本的int、string等类型,还包含结构体类型时,访问结构体类型成员不适用.变量名()/.set_变量名()
形式。
传入参数被const修饰时,访问内部非const函数,编译会遇到的问题和正常使用方式。
gRPC C++访问结构体成员
参考:
对于grpc中的结构体成员,通过:
request->mutable_B类型成员名b()
的方式访问,
查看分析grpc生成的.cpp和.h文件代码,生成的成员函数为mutable_
、set_allocated_
,通过这种方式访问和设置成员。
代码演示
另外分析函数入参被限定为const时的访问情况:
程序伪代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
// 假设 B b; 是A的成员变量
void func(const &B)
{
}
...(const A *request)
{
// A类中的成员b作为入参,调用func函数,表面上需要解引用作为入参,但直接解引用会报错
func(*request->mutable_b());
}
// grpc访问结构体成员
// 若request为const修饰的变量,要调用如下func函数的话,需要解引用,会出现const的this调用非const函数,编译报类似下面错误。
编译报错:
1
2
# const访问问题
错误:将‘const A’作为‘B* A::mutable_Bstructfield()’的‘this’实参时丢弃了类型限定 [-fpermissive]
正确使用方式:
可通过新增变量方式解引用:
1
2
3
auto a = new A; //注意资源的释放,可以改成智能指针防止忘记
a->CopyFrom(*request)
func(*a->mutable_b)
const成员函数功能及使用
参考
zh.cppreference.com: const、volatile 及引用限定的成员函数
对const修饰成员函数的功能作用,做一个说明和实例演示。
const、volatile 及引用限定的成员函数
- 非静态成员函数可声明为带有 const、volatile 或 const volatile 限定符(这些限定符出现在函数声明中的形参列表之后)。
- cv 限定性不同的函数具有不同类型,从而可以相互重载。
- 在 cv 限定的函数体内,this 指针被 cv 限定,const 成员函数中,只能正常地调用其他 const 成员函数。
参考中的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <vector>
struct Array {
std::vector<int> data;
Array(int sz) : data(sz) {}
// const 成员函数
int operator[](int idx) const {
// this 具有类型 const Array*
return data[idx]; // 变换为 (*this).data[idx];
}
// non-const member function
int& operator[](int idx) {
// this 具有类型 Array*
return data[idx]; // 变换为 (*this).data[idx]
}
};
int main()
{
Array a(10);
a[1] = 1; // OK:a[1] 的类型是 int&
const Array ca(10);
ca[1] = 2; // 错误:ca[1] 的类型是 int
}
自定义类编译演示
单独定义简单类进行编译演示const变量及const成员函数
印证:
- const 成员函数中,只能正常地调用其他 const 成员函数
- 定义的const 变量,只能访问非const成员函数
自定义一个类演示
成员函数以const在形参列表后修饰:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
using namespace std;
class Apple
{
public:
void print() const;
void func2();
void func3() const;
Apple():color(1){}
private:
int color;
};
void Apple::print() const
{
cout << __FUNCTION__ << endl;
// func2(); //编译报错:丢弃了类型限定 [-fpermissive]
func3();
cout << this->color << endl;
}
void Apple::func2()
{
cout << __FUNCTION__ << endl;
}
void Apple::func3() const
{
cout << __FUNCTION__ << endl;
}
int main(int argc, const char *argv[])
{
Apple apple;
apple.print(); // 以下调用都正常
apple.func2();
apple.func3();
const Apple apple2;
// apple2.func2(); //编译报错:将‘const Apple’作为‘void Apple::func2()’的‘this’实参时丢弃了类型限定 [-fpermissive]
return 0;
}
编译情况
1
2
3
4
[➜ /home/xd/workspace/src ]$ ./a.out
print
func3
1
放开print()函数中的 func2()
注释,编译报错:
1
2
3
[➜ /home/xd/workspace/src ]$ g++ test_const_func.cpp
test_const_func.cpp: 在成员函数‘void Apple::print() const’中:
test_const_func.cpp:19:8: 错误:将‘const Apple’作为‘void Apple::func2()’的‘this’实参时丢弃了类型限定 [-fpermissive]