如何使用C++成员指针访问子结构体的数据成员?
解决嵌套结构体成员的访问问题
你遇到的核心问题是:C++的原生成员指针只能表示某个类的直接成员,没法直接表达“先访问外层结构体的子结构体成员,再访问子结构体的成员”这种嵌套路径。要解决这个问题,我们可以把嵌套的访问逻辑包装成一个可调用对象,让addTogether函数接受这个对象来完成成员访问,同时保持原有直接成员调用的简洁性。
下面提供两种实用的解决方案:
方案1:使用Lambda表达式直接包装访问逻辑
这是最直观的方式,不需要额外的辅助代码,直接把嵌套访问写成lambda传给addTogether。我们需要先修改addTogether的模板参数,让它能接受任意可调用对象:
#include <iostream> #include <functional> // 可选,用于std::mem_fn简化直接成员调用 struct SubStruct { int c; }; struct MyStruct { int a; int b; float f; SubStruct ss; }; // 修改后的addTogether,接受任意可调用的访问器 template <typename Accessor> auto addTogether(Accessor access) { MyStruct s1 = {.a = 1, .b =2, .f =3.3, .ss = {.c = 4}}; MyStruct s2 = {.a = 10, .b =20, .f =30.0, .ss = {.c = 40}}; return access(s1) + access(s2); } int main() { // 直接成员可以用std::mem_fn简化,也可以写lambda std::cout << "sum a = " << addTogether(std::mem_fn(&MyStruct::a)) << std::endl; std::cout << "sum b = " << addTogether(std::mem_fn(&MyStruct::b)) << std::endl; std::cout << "sum f = " << addTogether(std::mem_fn(&MyStruct::f)) << std::endl; // 嵌套成员用lambda包装访问路径 std::cout << "sum c = " << addTogether([](const MyStruct& s) { return s.ss.c; }) << std::endl; return 0; }
运行后会输出:
sum a = 11 sum b = 22 sum f = 33.3 sum c = 44
方案2:实现成员指针组合函数,模拟嵌套成员指针
如果你希望调用方式更贴近原生成员指针的风格,可以写一个辅助模板函数,把外层成员指针和内层成员指针组合成一个可调用对象:
#include <iostream> struct SubStruct { int c; }; struct MyStruct { int a; int b; float f; SubStruct ss; }; // 组合两个成员指针:外层结构体的子成员指针 + 子结构体的成员指针 template <typename Outer, typename Inner, typename T> auto compose(T Inner::*inner_member, Inner Outer::*outer_member) { return [=](const Outer& obj) { // 先访问外层的子结构体,再访问子结构体的成员 return (obj.*outer_member).*inner_member; }; } template <typename Accessor> auto addTogether(Accessor access) { MyStruct s1 = {.a = 1, .b =2, .f =3.3, .ss = {.c = 4}}; MyStruct s2 = {.a = 10, .b =20, .f =30.0, .ss = {.c = 40}}; return access(s1) + access(s2); } int main() { // 直接成员可以直接传成员指针(编译器会自动适配可调用对象) std::cout << "sum a = " << addTogether(&MyStruct::a) << std::endl; std::cout << "sum b = " << addTogether(&MyStruct::b) << std::endl; std::cout << "sum f = " << addTogether(&MyStruct::f) << std::endl; // 用compose组合嵌套成员的指针 std::cout << "sum c = " << addTogether(compose(&SubStruct::c, &MyStruct::ss)) << std::endl; return 0; }
这个方案的好处是,调用嵌套成员时的写法更接近原生成员指针的语法,可读性更强。
为什么原来的写法不行?
你尝试的&MyStruct::ss::c和&MyStruct::ss.c都是无效语法:
&MyStruct::ss::c:ss是MyStruct的一个成员,不是类型,不能用::来访问它的成员;&MyStruct::ss.c:成员指针的语法只能是&类名::成员名,不能链式访问。
C++的成员指针本质上是指向类成员的偏移量,只能表示直接成员,无法存储嵌套的访问路径,所以必须用可调用对象来包装这个多步访问逻辑。
内容的提问来源于stack exchange,提问作者ianinini
相关产品推荐
相关产品推荐

