【问题标题】:can I access a struct inside of a struct without using the dot operator?我可以在不使用点运算符的情况下访问结构内部的结构吗?
【发布时间】:2010-05-10 23:31:45
【问题描述】:

我有 2 个结构,它们 90% 的字段相同。我想将这些字段分组到一个结构中,但我不想使用点运算符来访问它们。原因是我已经使用第一个结构进行了编码,并且刚刚创建了第二个。

之前:

typedef struct{
  int a;
  int b;
  int c;
  object1 name;
} str1;  

typedef struct{
  int a;
  int b;
  int c;
  object2 name;
} str2;

现在我要创建第三个结构:

typedef struct{
  int a;
  int b;
  int c;
} str3;

并将 str1 和 atr2 更改为:

typedef struct{
  str3 str;
  object1 name;
} str1;

typedef struct {
  str3 str;
  object2 name;
} str2;

最后我希望能够通过以下方式访问 a、b 和 c:

str1 myStruct;
myStruct.a;
myStruct.b;
myStruct.c;

而不是:

myStruct.str.a;
myStruct.str.b;
myStruct.str.c;

有没有办法做这样的事情。这样做的原因是,如果发生对结构的更改,我希望保持数据的完整性,并且不要重复自己,也不必更改我现有的代码,也不要让字段嵌套得太深。

已解决:感谢您的所有回答。这样做以便我可以使用自动完成的最后一种方法如下:

struct str11
{
int a;
int b;
int c;
};
typedef struct str22 : public str11
{
QString name;
}hi;

【问题讨论】:

  • 你的代码对我来说是零意义的。 str3 不是类型,而是对象。声明str3 str 毫无意义。当你声明结构时,说struct str3 { ... }; 而不是struct { ... }str3;
  • 这就是为什么你没有找到答案,但其他人都找到了。
  • 来自维基百科:typedef 是 C 和 C++ 编程语言中的关键字。 typedef 的目的是为现有类型分配替代名称。来自我:我猜它毕竟是一种类型,这取决于姜黄。
  • 你在哪里看到 typedef?您上面的代码创建了两个匿名类型,并为它们创建变量 str1 和 str2 实例(然后对 str3 再次执行相同操作)。如果您要尝试攻击评论者,至少要让您的事实正确。
  • 人们对您的主题做出反应的“攻击”是怎么回事? @Wilhelm/dash/Maciej

标签: c++ c struct


【解决方案1】:

是的。而是使用 C 风格的继承,使用 C++ 风格:

struct str3{
  int a;
  int b;
  int c;
};

struct str2 : public str3{
  object2 name;
};

【讨论】:

  • 它可以工作,但现在如果我使用自动完成功能,Qt 不会向我建议这些字段,也许如果我重新启动 qt 或从头开始重建或...
  • 我在你的帖子中没有看到任何关于 Qt 的内容。
  • 我冒昧地猜测,在您的资源至少得到最低限度的保存之前,Qt 不会重新生成它的自动完成信息。我不能肯定地说,因为我不使用 Qt。 (而且我认为 Qt 是一个库集,而不是一个 IDE?)我可以告诉你,鉴于上面的代码,这将编译(假设没有奇怪的 #define's): str2 foo; foo.a = 1; foo.b = 2; foo.c = 3; foo.name = "酒吧"; /* 抱歉格式不好,不能在评论中发布多行格式的代码? */
  • 我猜他指的是QtCreator。
  • @Georg @yan:在答案之后添加随机细节通常意味着您需要一个新问题,或者它应该存在。
【解决方案2】:

第一句话。这个

struct
{
  int a;
  int b;
  int c;
} str3;

定义一个对象 str3,而不是类型 str3。

你可以使用继承来实现你想要的,但我建议改变你的结构的数量

struct str1
{
  int a;
  int b;
  int c;
};


struct str2 : public str1
{
  object1 name;
};  

【讨论】:

  • 只是再次跟进-这里创建的类型的名称是什么?它不是您从帖子中所想的“str3”。
  • @Yan:不,你不能像以前那样。您的示例创建未命名类实例
  • @Yan: #1 是 Microsoft 扩展并定义一个 匿名实例 并为此使用类型名称,#2 确实提供了一些 IDL具体的事情,IDL 基本上是一种不同的语言。在标准 C++ 中,struct {} x; 定义了一个匿名类类型的实例。
  • 试试吧,你会看到,我刚刚查找了一些可以做到这一点的 c 代码,它来自一位在这方面工作了 25 年的嵌入式工程师,他的工作被 NASA 使用
  • @Yan:我不知道你的编译器作为 standard C++ 的扩展做了什么,但我的说例如"'str3' does not name a type" 使用您问题中的代码。仅仅因为一个编译器允许它并不意味着它在标准中。如果您仍有疑问,请提出相关问题。
【解决方案3】:

这样做的原因是如果结构发生变化,我想保持数据的完整性

为了实现这一点,我宁愿使用适当的封装、访问器和继承来使布局更改对用户代码不可见:

class DataHolder {
    int a_, b_, c_;
public:
    int a() const { return a_; }
    int b() const { return b_; }
    int c() const { return c_; }
};

class User : public DataHolder {
    object o_;
public:
    object& getObject() { return o_; }
};

【讨论】:

  • @GMan:呃,它一定是一夜之间长大的——但我现在什至收到了@ 通知;)
【解决方案4】:

我不确定 C++(我还在学习 C++),但在 C 中,一些编译器允许匿名结构。在 GCC 4.3 中,以下在未指定标志时编译没有错误,但使用 -ansi-std=c99 编译失败。但是,它使用-std=c++98 成功编译:


int main (int argc, char *argv[])
{
    struct
    {
        struct
        {
            int a;
            int b;
            int c;
        };
        int test;
    } global;

    global.a = 1;
    global.b = 2;
    global.c = 3;
    global.test = 4;

    return global.b;
}

【讨论】:

  • 如果我不需要在另一个结构中重用该结构,这将起作用
【解决方案5】:

不要使用愚蠢的技巧来避免适当的重构。它会为您节省一点打字时间,但它会咬住您的……稍后。如果编辑起来那么复杂,那么您使用了错误的工具和/或您的命名方案不正确(很难找到/替换 1 个字母的名称)。

【讨论】:

    【解决方案6】:

    您可以使用 GCC 来执行此操作,就像其他海报 mentioned 一样,但除此之外,您还可以使用 -fms-extensions 标志,该标志允许您使用之前定义的 struct 作为未命名字段。

    更多here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-25
      • 2013-02-02
      • 1970-01-01
      • 2020-04-08
      • 2016-09-10
      • 2013-04-22
      • 2020-12-21
      • 2018-01-13
      相关资源
      最近更新 更多