【问题标题】:Printing values of all fields in a C++ structure打印 C++ 结构中所有字段的值
【发布时间】:2010-05-03 14:56:35
【问题描述】:

考虑一个简单的结构:

struct abc  
{  
    int a;  
    char b;  
}  

我在一个定义为其结构的变量中获得了一些值,现在我想打印以下内容。

*a = [some value]  
b = [some character]*

对于任意结构,无需为我遇到的每个结构编写转储...(...)函数的最佳方法是什么?

【问题讨论】:

标签: c++ visual-c++ structure


【解决方案1】:

看来您已经找到了解决方案,但我会扩展一下。

您所要求的称为Reflection,即对象描述自身的能力。

由于元数据,大多数语言都可以实现反射。例如,在 Python 中,对象的函数和属性存储在字典元素中。

C++ 没有任何与 C# 或 Java 不同的本机反射系统,这会阻止(例如)这种自动打印/序列化或反序列化。

但是,C++ 具有非常强大的元编程支持,它允许我们(通过使用模板)模拟反射(在编译时)。这通常使用Boost.Fusion 完成,这是一个用于从编译时跨越到运行时的库。

如链接中所示的示例,BOOST_FUSION_ADAPT_STRUCT 宏允许您采用标准 struct 并为其提供所需的接口,以将其视为 Fusion.Sequence。

另一个例子是使用Fusion.VectorFusion.Map 来存储类的属性,然后将此序列公开给自动打印/序列化/反序列化方法。

但是,这个系统有一个限制:元编程与 OO 编程不能很好地结合。

struct Base { char a; };            // Adapt
struct Derived: Base { char b; };   // Adapt

void print(Base const& b) { boost::fusion::for_each<Base>(b, Print()); }

只会打印Base 的成员(这里是a)。使用多态性时,您需要在某一时刻使用virtual 方法:)

【讨论】:

【解决方案2】:

您需要“反思”才能做到这一点。 C++ 本身不提供反射,或者仅针对最少的信息(类型 ids/names)提供反射。

有一些库(如CAMP)实现了反射功能,所以如果你真的需要反射,你应该使用一个。

【讨论】:

    【解决方案3】:

    使用 C++17(甚至可能是 C++14)和一些疯狂的俄罗斯黑客 - 可以部分完成。即可以按顺序打印类型值,但不能获取字段名。

    相关库是 Antony Polukhin 的 "magic_get"。具体来说,它提供了一个“针对每个字段”的迭代 mechanism,它采用带有 auto 参数类型的模板化 lambda。示例:

    struct simple {
        int a;
        char b;
        short d;
    };
    
    simple x {42, 'a', 3};
    std::stringstream ss;
    
    boost::pfr::for_each_field(
        x,
        [&ss](auto&& val) {
            ss << val << ' ';
        }
    );
    

    答案来自一个相关/重复的问题 - 因为这里没有人提到这一点。

    【讨论】:

      【解决方案4】:

      没有,在 C++ 中没有。运气不好。

      【讨论】:

      • 有多种方法可以做到这一点:模板元编程、解析或使用外部工具生成类。不要忘记使用计算机可以实现很多事情,尽管可能并不容易,或者以您认为应该的方式。
      • There are reflection libraries,反射正在进入标准。这个答案现在已经过时了
      【解决方案5】:

      如果您在 .NET 中使用 C++,您可能会使用 System.Reflection 东西来查看您的结构的内部结构。不过,非托管 C++ 很少(如果有的话)存储关于对象的那种元数据。

      【讨论】:

        【解决方案6】:

        就这样做

        #include<iostream>
        using namespace std;
        struct abc  
        {  
            int a;  
            char b;  
        };
        void display(abc myStruct){
           cout << "struct abc {"<< endl;
           cout << abc.a << endl;
           cout << abc.b << endl;
           cout << "}" << endl;
        }
        int main(){
            abc myStruct
            display(myStruct);
        }
        

        仅当结构是用户定义而不是由您定义并且您不确定结构的内部结构时才需要反射。

        【讨论】:

          猜你喜欢
          • 2022-06-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-22
          • 1970-01-01
          • 2017-03-19
          相关资源
          最近更新 更多