【问题标题】:Calling function before objects are created in a class在类中创建对象之前调用函数
【发布时间】:2015-12-01 08:11:02
【问题描述】:

基本上,我有一个拥有另一个对象的类:

class A()
{
    A() { initSystems() };
    void initSystems();
    B b;
}

class B()
{
    B() { //Does stuff that requires 'initSystems()' to be called before }
}

为了使“B”起作用,需要在 A 中调用 init 系统函数。有什么“好”的方法可以解决这个问题吗?比如稍后创建“B”对象之类的?

【问题讨论】:

    标签: c++ design-patterns dependencies


    【解决方案1】:

    听起来你的课太tightly coupled。有很多方法可以解决这个问题,但这取决于您的设计的其余部分。

    也许 A 不应该拥有 B,因为 A 是 B 的依赖项。您可以 inject 在每个 B 实例化时将 A 的实例添加到每个 B 中。

    也许B不应该存在,应该合并到A中:

    class A()
    {
        A() {
            initSystems();
            //Does stuff that requires 'initSystems()' to be called before
        }
        void initSystems();
        // B's methods
    }
    

    我认为大多数初始化方法都是代码异味(也就是说,它暗示了一个糟糕的设计)。有人给这个模式起了个名字:"Design Smell: Temporal Coupling"

    【讨论】:

      【解决方案2】:

      如果你想让 B 成为 A 的普通成员,那么在构造 b 之前可以运行代码的两个地方是:

      1. A 的基类的构造函数,
      2. 在 A 的成员的初始化列表中,对于上面声明的成员 b

      如果您希望推迟 B 的构建,您需要通过间接方式保存对象,或者稍后将其构建到原始存储中,并在销毁时执行放置销毁。

      其中大部分都有奇怪的气味,重组代码以避免这种结构可能是有益的。

      【讨论】:

      • 感谢您的回复,那么在 A 中存储指向 B 类的指针 (B* b;) 是否是个好主意,然后在我在构造函数中调用 initSystems() 之后对其进行初始化( b = new b(); ),还是我应该专注于重新设计我的课程? (实际上,A 类是一个“游戏”类,它实际上是第一个运行的东西,而 B 类是一个渲染器类,用于将游戏对象渲染到屏幕上)
      • @TheInfernalCow 如果您的游戏本质上是单实例的,您可能希望将粘合和托管责任从其中移到同时了解系统和嵌套实体的东西中。就目前而言,这似乎太负责任了。
      【解决方案3】:

      您只需要更改您的设计,因此initSystems()AB 的要求。

      如果你不能这样做(虽然你确实应该这样做),还有其他方法,比如动态分配:

      class A()
      {
          A() { 
            initSystems(); 
            b = std::make_unique<B>();
          };
          void initSystems();
          std::unique_ptr<B> b;
      }
      

      【讨论】:

        【解决方案4】:

        我同意@nanny 关于类的解耦并尽可能合并。

        但是您的情况似乎是 B 是您系统中的单独实体,因此是一个类。而 A 包含一个 B,因此构成。

        因此,解决此问题的一种方法是,在 A 中保留指向 B 的引用(指针),而不是使 B 成为 A 的一部分。

        或者您不应该在 B 的构造函数中访问在 A 的 initInstance() 中创建的内容,并在 B 中创建一个方法 postConstruct,您可以在调用 initInstance 后从 A 调用该方法。下面的代码解释了它,

        class A()
        {
            A()
            { 
                initSystems();
                b.postContruct()
            }
            void initSystems()
            {
                // do the init instance stuff here.
            }
            B b;
        }
        
        class B()
        {
            B() {}
        
            void postContruct()
            { 
               //Does stuff that requires 'initSystems()' to be called before 
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-11-10
          • 2016-05-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多