You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过动态字符串变量获取结构体成员的值?

通过字符串访问C++结构体成员的解决方案

好问题!C++作为静态类型语言,确实不像一些动态语言那样能直接用字符串名字访问结构体成员,咱们一步步来拆解这个问题:

为什么str1.c_str()直接用不行?

首先明确:str1.c_str()只是把std::string转换成C风格的const char*字符串,本质还是运行时的文本数据。而结构体成员名是编译期就确定的符号,编译器在编译阶段需要明确知道你要访问哪个成员,没办法把运行时的字符串自动映射到编译期的成员符号上。所以直接用str1.c_str()是做不到直接访问frmt.day的。

可行的实现方法

下面是几种常用的解决方案,都是通过提前建立字符串和成员的映射关系来实现:

方法1:用std::unordered_map绑定成员访问函数

这种方法灵活性高,支持不同类型的成员(如果你的结构体成员类型不一样也能处理)。示例代码如下:

#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>

// 定义你的结构体
struct Frmt {
    int day;
    std::string month;
    double year;
};

int main() {
    // 初始化结构体
    Frmt frmt = {15, "August", 2024.0};
    std::string str1 = "day";

    // 建立字符串到成员访问函数的映射
    std::unordered_map<std::string, std::function<void(const Frmt&)>> memberAccess = {
        {"day", [](const Frmt& f) { std::cout << f.day << std::endl; }},
        {"month", [](const Frmt& f) { std::cout << f.month << std::endl; }},
        {"year", [](const Frmt& f) { std::cout << f.year << std::endl; }}
    };

    // 通过字符串访问对应成员
    if (memberAccess.find(str1) != memberAccess.end()) {
        memberAccess[str1](frmt); // 输出15
    } else {
        std::cout << "不存在该成员" << std::endl;
    }

    return 0;
}

如果需要获取成员的值而不是直接输出,可以把std::function的返回类型改成对应成员的类型,比如std::function<int(const Frmt&)>对应day

方法2:用成员指针配合字符串匹配

如果结构体成员类型相同,这种方法更简洁:

#include <iostream>
#include <string>
#include <vector>
#include <utility>

struct Frmt {
    int day;
    int month;
    int year;
};

int main() {
    Frmt frmt = {15, 8, 2024};
    std::string str1 = "day";

    // 建立字符串到成员指针的映射
    const std::vector<std::pair<std::string, int Frmt::*>> memberMap = {
        {"day", &Frmt::day},
        {"month", &Frmt::month},
        {"year", &Frmt::year}
    };

    // 查找并访问成员
    for (const auto& pair : memberMap) {
        if (pair.first == str1) {
            std::cout << frmt.*pair.second << std::endl; // 输出15
            break;
        }
    }

    return 0;
}

方法3:借助反射库(进阶)

如果你的项目允许引入第三方库,比如Boost.Reflection,或者使用C20及以后的实验性反射特性(注意原生C目前还没有完全支持编译期反射),可以实现更自动化的映射,但这种方式复杂度较高,适合大型项目。

内容的提问来源于stack exchange,提问作者kishore

火山引擎 最新活动