【问题标题】:C++ How to access a Global Object from Member Objects within the Global ObjectC++ 如何从全局对象中的成员对象访问全局对象
【发布时间】:2016-05-09 09:50:09
【问题描述】:

生日,

使用 C++,我想要一个包含多个公共成员对象的全局对象,这些公共成员对象可以“通过”全局对象进行访问,同时成员对象中的代码应该能够调用通过将全局对象作为全局对象进行访问(即不将全局对象的特定引用传递给成员对象)。

我认为这会很简单,就像下面我简化的示例代码一样,但它不会编译。在 IDE 中,查看头文件时,我收到“重新定义 GlobalObject / MemberObject”和“未知类型名称”警告(尽管每个头文件中都有“pragma once”?)。当我编译代码时,编译器会报告“GlobalObject / MemberObject is undefined”错误。

我想我有某种循环引用问题,但老实说我不明白为什么,因为虽然全局对象包含对成员对象的引用,但成员对象却没有t 包含对全局对象的引用,因为我打算让它们以与任何其他代码直接从主函数访问它的方式相同的方式访问全局对象......?通过在主函数之外声明 GlobalObject 然后在 MemberObject 头文件中将其作为外部引用来实现 GlobalObject 不是全局的,还是我在这里弄错了?

我知道人们对全局对象的邪恶有强烈的看法,但我相信在某些情况下它们是合适的,特别是在资源有限且本质上是“启动”而不是“关闭”的嵌入式系统中(或者至少不要以受控方式关闭 - 电源刚刚关闭)。所以我想知道如何才能使我正在尝试做的事情发挥作用,或者如果不能,我想了解为什么不这样做。

如果有人愿意提供任何指导,我将不胜感激,谢谢。

GlobalObject.h

#pragma once

#include "MemberObject.h"

class GlobalObject
{
  private:
    int               Data;
    int               Total;

  public:
    GlobalObject();
    MemberObject      MO;
    int               GetData(void);
    void              SetData(int NewData);
    int               GetTotal(void);
    void              SetTotal(int NewTotal);
};

GlobalObject.cpp

#include "GlobalObject.h"

GlobalObject::GlobalObject() : MO()       { Data = 0; Total = 0; }

int  GlobalObject::GetData(void)          { return Data; }
void GlobalObject::SetData(int NewData)   { Data = NewData; }

int  GlobalObject::GetTotal(void)         { return Total; }
void GlobalObject::SetTotal(int NewTotal) { Total = NewTotal; }

MemberObject.h

#pragma once

#include "GlobalObject.h"

extern GlobalObject GO;

class MemberObject
{
  private:
    int               Data;

  public:
    MemberObject();
    int               GetData(void);
    void              SetData(int NewData);
    void              SetGlobalTotal(void);
};

MemberObject.cpp

#include "MemberObject.h"

MemberObject::MemberObject()              { Data = 0; }

int  MemberObject::GetData(void)          { return Data; }
void MemberObject::SetData(int NewData)   { Data = NewData; }

void MemberObject::SetGlobalTotal(void)   { GO.SetTotal(GO.GetData() + Data); }

main.cpp

#include "GlobalObject.h"

GlobalObject GO;

int main(void)
{
  GO.SetData(1000);
  GO.MO.SetData(2000);
  GO.MO.SetGlobalTotal();
}

【问题讨论】:

  • 你知道#include 是如何工作的吗?您不能有两个文件相互包含的循环。 (嗯,你可以,但它不会像你期望的那样工作)

标签: c++


【解决方案1】:

这是您在设计课程时应尽量避免的事情。

如果全局对象是单例,一种选择是对该对象进行全局引用,然后每个人都可以通过该引用进入。 (这在日志框架、资源池等方面很常见。) Trevor Hickey 的回答使用了这个选项。

唯一的另一种方法是让子对象明确了解父对象:MemberObject 构造函数可以接受对其父对象GlobalObject 的引用。 (不要使用指针,因为这会导致三规则问题)

【讨论】:

  • 我一直在摆弄这个问题,并开始接受你是对的。我希望父级及其子级是自包含的,因此我只需要实例化父级的一个实例即可使用它及其子级。所以我认为你的第二个选择是要走的路。 (不知何故,我现在觉得在我开始使用全局父方案之前我应该​​知道这一点,因为我以前通过在子 ctors 中传递父指针来做到这一点)。我现在注意到你所说的传递引用而不是指针,但是获取对父级的引用以传递给子级的“正确方法”是什么?
  • 从父母那里传递*this
  • 感谢您的建议。根据您的建议,该项目的这方面已成功完成。
【解决方案2】:

似乎是什么问题?

struct Member{
  void method(){}
};

struct Global{
  Member member;
};

//global instance
Global global;

int main(){
  global.member.method();
}

【讨论】:

  • 特雷弗,感谢您的关注。我看到你建议的是结构而不是类。我不知道这有什么意义,但会对此进行调查和测试。但是你能简要解释一下你想要的区别是什么吗?谢谢。
  • struct 默认为publicclassprivatestackoverflow.com/questions/54585/…
  • 你好。我认为公共与私人的区别与我的问题无关?我现在已经阅读了一些内容并对此进行了实验,但我认为它不会改变任何东西。
【解决方案3】:

使用 C++,我想要一个包含多个公共成员对象的全局对象,这些公共成员对象可以“通过”全局对象进行访问,同时成员对象中的代码应该能够调用通过将全局对象作为全局对象进行访问(即不将全局对象的特定引用传递给成员对象)。

虽然您可以这样做,但它指出了您的设计中可能存在的缺陷。理想情况下,全局对象的成员对象不应依赖全局对象来完成它们的工作。我建议您退后一步,重新考虑您的设计。

我能给出的最简单的类比是,链表的节点不依赖于链表的良好定义和工作。另一方面,链接列表依赖于节点的详细信息来完成其工作。

【讨论】:

  • 您好 R Sahu,感谢您的关注。我相信我理解您的观点,尽管在这种情况下,我认为我的方法是合理的。我上面提供的代码只是我遇到的问题的一个简单演示。事实上,我正在为某些硬件编写一种设备驱动程序,并且硬件足够复杂,以至于我想将驱动程序的某些部分实现为“子组件”,尤其是在它们有多个实例的情况下。但在某些情况下,当更改“子组件”中的设置时,我需要子组件代码更新顶级驱动程序对象中的设置...
  • @MartinIrvine,在这种情况下,signals and slots mechanism 值得研究。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 2011-08-25
相关资源
最近更新 更多