【问题标题】:Is it possible to step through the members of a C++ struct?是否可以单步执行 C++ 结构的成员?
【发布时间】:2011-06-10 09:52:28
【问题描述】:

我想单步调试 C++ 结构的成员并打印出它们的值。我可以很容易地显式编写代码,但是有没有什么方法可以在不知道结构中的内容的情况下做到这一点?

我想我正在寻找与 C# 的 foreach 命令等效的 C++。

感谢您的帮助。

添加:我在 C# 中做这样的事情。此代码从先前读取的 XML 文件中设置结构成员:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SettingsStruct
{
    public uint nLength;
}

private void UpdateSettings()
{
    SettingsStruct settings = new SettingsStruct();

    foreach (FieldInfo fieldInfo in typeof(SettingsStruct).GetFields())
    {
        string settingName = "SETTING." + fieldInfo.Name.ToUpper();
        if (appSettings.Contains(settingName))
        {
            switch (fieldInfo.FieldType.FullName)
            {
                case "System.UInt32":
                    fieldInfo.SetValueDirect(__makeref(settings), uint.Parse((string)appSettings[settingName]));
                    break;
            }
        }
    }
}

【问题讨论】:

标签: c# c++


【解决方案1】:

如果您愿意使用 boost fusion,您可以这样做。首先将这个结构“提升”为一个融合序列,然后你可以遍历序列打印出每个成员。

【讨论】:

    【解决方案2】:

    你可以为你的结构重载operator<<,然后你只需要编写一次代码。

    【讨论】:

      【解决方案3】:

      以下 Stackoverflow 答案应该让您了解您在寻找什么

      Iterate Over Struct; Easily Display Struct Fields And Values In a RichEdit Box

      【讨论】:

        【解决方案4】:

        不怕。 C++ 提供有限的反射能力。 RTTI C++ 系统允许您访问类型,但不能自省该类型中的字段。

        通过一些宏魔法/骇客,您也许可以实现这一点,请参阅Reflection for C++ 以获取示例。

        【讨论】:

          【解决方案5】:

          foreach 命令不会执行您在 C# 中所说的操作。 foreach 遍历集合(数组、集合、列表...)的 元素,而不是结构的成员(比如“长度”...)。

          C++ 中 foreach 的等价物是使用迭代器(xs.begin()、xs.end())。您可以使用 BOOST_FOREACH 来获得更简洁的语法(或 C++1x 中的 for(X& s : xs))。

          【讨论】:

            【解决方案6】:

            C++ 不允许对一般类成员进行迭代。但是,如果您准备接受一些限制,并使用某些人认为纯粹是邪恶的技术,您可以建立一个框架来允许对特定类类型家族的成员进行迭代。这是通过滥用默认赋值运算符递归应用于类的所有成员这一事实来实现的。

            首先我们需要声明要包含在迭代中的类型:

            struct Visitable1;
            struct Visitable2;
            struct Visitable3;
            

            我们还需要一个抽象基类,以便在迭代时执行操作(为简洁起见省略了析构函数;为安全起见,它应该是虚拟的或受保护的):

            struct Visitor
            {
                virtual void visit(Visitable1 &) = 0;
                virtual void visit(Visitable2 &) = 0;
                virtual void visit(Visitable3 &) = 0;
            
                static Visitor * current;
            };
            

            以及我们可以在迭代中包含的类型的基类(使用“奇怪的递归模板”习语);这就是操作符滥用发生的地方,修改了自赋值的行为:

            template <typename T>
            struct Visitable
            {
                void operator=(Visitable const & other)
                {
                    if (&other == this) {
                        Visitor::current->visit(static_cast<T&>(*this));
                    }
                }
            };
            
            struct Visitable1 : Visitable<Visitable1> { /* some stuff */ };
            struct Visitable2 : Visitable<Visitable2> { /* some stuff */ };
            struct Visitable3 : Visitable<Visitable3> { /* some stuff */ };
            

            最后,我们可以定义迭代本身:

            template <class T, class Visitor>
            void for_each(T & t, Visitor v)
            {
                Visitor::current = &v;
                t = t;
            }
            

            这确实有一些明显的缺点:

            • “访问”函数是虚拟的,因此不能是通用的。我目前想不出一种方法来允许在没有抽象基类的情况下使用不同的访问者类。因此,迭代只能应用于预先声明的一组类型。
            • 使用静态变量 (Visitor::current) 意味着任何时候都只能进行一次迭代,从而导致线程安全和重入问题。我目前想不出更好的方法将状态传递给operator=,因为这仅在重载默认operator= 时有效,并且具有与受让人相同类型的单个参数。
            • 如果有人发现您编写这样的代码,您可能会被处以私刑。

            请参阅codepad.org 进行演示。

            【讨论】:

              猜你喜欢
              • 2021-06-15
              • 1970-01-01
              • 2022-11-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-07-18
              • 2012-11-16
              • 2014-08-03
              相关资源
              最近更新 更多