Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用c+;打印变量名的通用方法+;_C++_Variables_Printf_Iostream - Fatal编程技术网

C++ 用c+;打印变量名的通用方法+;

C++ 用c+;打印变量名的通用方法+;,c++,variables,printf,iostream,C++,Variables,Printf,Iostream,上课 struct { int a1; bool a2; ... char* a500; ... char a10000; } 我想打印或流式输出 "a1 value is SOME_VALUE" "a2 value is SOME_VALUE" "a500 value is SOME_VALUE" ... "a10000 value is SOME_VALUE" 成员变量的类型不相同(主要是int、bOL、char *等),即不需要重载,因为C++中

上课

struct {
  int a1;
  bool a2;
  ...
  char* a500;
  ...
  char a10000;      
}
我想打印或流式输出

"a1 value is SOME_VALUE"  
"a2 value is SOME_VALUE"
"a500 value is SOME_VALUE"
...
"a10000 value is SOME_VALUE"

成员变量的类型不相同(主要是int、bOL、char *等),即不需要重载,因为C++中没有反射,所以无法在C++中枚举类的成员。因此,不能访问变量名。

您可以使用指向成员的指针

void PrintMemberValue(int MyClass::*p, MyClass const & obj)
{
    cout << "Member has value " << obj.*p;
}

MyClass obj;
int MyClass::*p = &MyClass::a1;
PrintMemberValue(p, obj);
p = &MyClass::a2;
PrintMemberValue(p, obj);
etc
void PrintMemberValue(int MyClass::*p,MyClass常量和obj)
{

CUT< P>你所寻找的特征通常是被调用的。它不是C++的一部分,因为在编译语言中,你所要处理的信息(人类可读变量名)通常不被编译器保存。不需要运行代码,所以没有包含它的含义。 调试器通常可以检查带外符号信息,或为此目的保存在二进制文件中的符号数据,以显示此类名称,但为此目的重新执行此操作可能需要做更多的工作


我建议您自己寻找一些“技巧”(=解决方案)来实现这一点。

您可以使用一个邪恶的宏:

#define DUMP(a) \
    do { std::cout << #a " is value " << (a) << std::endl; } while(false)
#定义转储(a)\
这是不可能的(见其他答案)


一种解决方法是使用自动代码生成。您将字段定义写入一个文件中,然后从中生成.h和.cpp文件。我将其用于一个大约有100个类和许多字段的代码。它能够生成代码以将它们发送到流(主要是调试)对于Socket通讯来说,它非常可靠(从来没有测试过任何功能),但是因为它不是纯C++,所以它可能不是你的解决方案。

< P> >代码>手表< /Cord>宏是有史以来最有用的技巧之一。
#define watch(x) cout << (#x) << " is " << (x) << endl

#define watch(x)coutGDB可以打印结构。此脚本生成GDB脚本,用于在GDB#U指定的打印位置设置断点和打印值:

gdb-print-prepare()
{

    # usage:
    # mark print points with empty standalone defines:
    # gdb_print(huge_struct);
    # gdb-print-prepare $src > app.gdb
    # gdb --batch --quiet --command=app.gdb $app
    cat  <<-EOF
    set auto-load safe-path /
    EOF
    grep --with-filename --line-number --recursive '^\s\+gdb_print(.*);' $1 | \
    while IFS=$'\t ;()' read line func var rest; do
        cat  <<-EOF
        break ${line%:}
        commands
        silent
        where 1
        echo \\n$var\\n
        print $var
        cont
        end
        EOF
    done
    cat  <<-EOF
    run
    bt
    echo ---\\n
    EOF
}
gdb-print-prepare()
{
#用法:
#使用空的独立定义标记打印点:
#gdb_打印(大型结构);
#gdb打印准备$src>app.gdb
#gdb--批处理--安静--命令=app.gdb$app

老牌的cat解析了
gcc-g-s
的输出,以获得可用形式的信息。它本来是用于perl的,但是你可以将它用于这种方法。有时需要一个邪恶的宏来修补语言中的一个漏洞。嗨,sehe,谢谢你的回答。但是你仍然需要键入a1、a2、a3。。。,这并不是比“printf(“a1…”)、printf(“a2…”);…”更大的改进或通用方法。如果我有10000个变量呢?嗯……那么你就…(a)搞错了(b)做错事了。结构中的10000个变量:你应该使用容器。另外,看看序列化框架(他们仍然不打印成员名称,但我认为这是你的类的一个设计问题)嗨,sehe,似乎没有通用的方法存在。我支持你的帖子,但接受unwind的回答,指出反射:-“有趣的宏”下的链接似乎断开了。为什么它是“邪恶的”?如果你(a)的话,这可能是最好的方法不想或不能使用外部库,并且(b)有太多的类/结构成员,无法合理地手动复制粘贴宏(sehe的答案)。(或者如果结构/类代码经常更改,您担心最终会有人出现复制粘贴错误。)有些框架,但这不是一个本地语言特征。在C++中没有通用的方法来做你想做的事情。你应该问问自己是否使用了正确的工具来做这个工作。考虑C++中的另一种语言,或者不同的数据结构,也许是矢量或列表。此外,你真的做不好。{ STD::A.Y.Buf(0)=“h”A.Y-Buf(1)=“A`.Buf”[2 ] =“L”,A.Buf(0)=“L”< /代码>,或者您更希望“代码”>“hello,Word \n”/COD>?C++有一个清晰的概念,即“打印代码<结构FoO < /代码>”,并且是用<代码>操作符编写的。
gdb-print-prepare()
{

    # usage:
    # mark print points with empty standalone defines:
    # gdb_print(huge_struct);
    # gdb-print-prepare $src > app.gdb
    # gdb --batch --quiet --command=app.gdb $app
    cat  <<-EOF
    set auto-load safe-path /
    EOF
    grep --with-filename --line-number --recursive '^\s\+gdb_print(.*);' $1 | \
    while IFS=$'\t ;()' read line func var rest; do
        cat  <<-EOF
        break ${line%:}
        commands
        silent
        where 1
        echo \\n$var\\n
        print $var
        cont
        end
        EOF
    done
    cat  <<-EOF
    run
    bt
    echo ---\\n
    EOF
}