如何将字符串向量传递给宏以访问C++类成员变量?
通过字符串变量访问C++类成员的编译错误及解决方法
问题代码
#include <iostream> #include <vector> #define DECLARE(X, i) #X->i class dut{ public: int clock; double reset; dut(int a, int b){ this->clock = a; this->reset = b; } ~dut(); }; int main(int argc, char **argv){ dut *d = new dut(4, 5); std::vector<std::string>var; var.push_back("clock"); var.push_back("reset"); std::vector<std::string>::iterator it; for(it = var.begin(); it != var.end(); ++it){ std::cout << DECLARE(d, *it) << std::endl; } return 0; }
编译错误
error: expected unqualified-id before ‘*’ token 25 | std::cout << DECLARE(d, *it) << std::endl;
错误原因
宏是预处理阶段执行的工具,只能处理编译期确定的字面量,无法识别运行时的变量:
#X是宏的字符串化操作,会把参数X直接转换成字符串字面量,所以DECLARE(d, *it)会被预处理成"d"->*it。- 字符串字面量不能用
->访问成员,且*it是运行时才会确定值的字符串变量,预处理阶段根本无法解析它的内容,最终生成非法语法导致编译报错。
解决方案
C++是静态类型语言,无法直接通过运行时字符串访问类成员,需要手动建立字符串到成员的映射关系,以下是两种可行方案:
方案1:使用成员指针+变体类型映射
利用std::unordered_map存储字符串到成员指针的映射,用std::variant兼容不同类型的成员:
#include <iostream> #include <vector> #include <unordered_map> #include <variant> class dut{ public: int clock; double reset; dut(int a, int b) : clock(a), reset(b) {} ~dut() = default; }; int main(int argc, char **argv){ dut *d = new dut(4, 5); std::vector<std::string> var = {"clock", "reset"}; // 建立字符串到成员指针的映射 std::unordered_map<std::string, std::variant<int*, double*>> member_map = { {"clock", &d->clock}, {"reset", &d->reset} }; for(const auto& name : var){ auto map_it = member_map.find(name); if(map_it != member_map.end()){ // 访问并打印对应成员的值 std::visit([](auto ptr){ std::cout << *ptr << std::endl; }, map_it->second); } } delete d; return 0; }
方案2:直接判断字符串(适合成员数量少的场景)
如果类成员数量不多,直接通过if-else判断字符串名称,直接访问成员:
#include <iostream> #include <vector> class dut{ public: int clock; double reset; dut(int a, int b) : clock(a), reset(b) {} ~dut() = default; }; int main(int argc, char **argv){ dut *d = new dut(4, 5); std::vector<std::string> var = {"clock", "reset"}; for(const auto& name : var){ if(name == "clock"){ std::cout << d->clock << std::endl; } else if(name == "reset"){ std::cout << d->reset << std::endl; } } delete d; return 0; }
内容的提问来源于stack exchange,提问作者Ben Eslami
相关产品推荐
相关产品推荐

