1

假设我需要在构造函数初始化任何成员变量之前调用一个免费的 GlobalInitializer()。例如:

class Foo {
  public:
    Foo() : bar_()
    {
      // calling GlobalInitializer() here is too late
    }
  Bar bar_;
};

在 Foo 中调用 GlobalInitializer() 为时已晚,因为我需要在 bar_ 初始化之前调用它。为此,我的 hacky 工作是创建一个超类:

class MyInitializer {
  protected:
    MyInitializer() {
      GlobalInitializer();
    }
};
class UglyFoo : public MyInitializer
{
  public:
    UglyFoo() : bar_()
    { }
  Bar bar_;
};

UglyFoo 完成了工作,但它需要这个丑陋的 MyInitializer 类。是否有更简洁的设计模式或重构可以达到相同的结果?

附加说明: GlobalInitializer() 是一个昂贵的调用,除非用户实例化 Foo(),否则我想避免这种调用。GlobalInitializer() 内部有针对多个调用的保护。此外,可能还有其他类,比如 FooBar,也需要调用 GlobalInitializer(),但在一个进程中,GlobalInitializer() 实际上会工作一次(如果 Foo 或 FooBar 被实例化)甚至一次都不会(如果没有Foo 或 FooBar 的实例化)。

4

5 回答 5

4
class Foo {
private:
    struct Initializer {
        Initializer() { GlobalInitializer(); }
    };
    Initializer initializer__;  // declare before bar__ to ensure it is constructed first

public:
    Foo() : bar_()
    {
    }

    Bar bar_;
};
于 2011-10-20T11:25:50.470 回答
1

您可能应该重新考虑您的设计。

一个好的设计意味着松耦合。如果您的对象创建依赖于不同的方法调用来工作,那么那里就会出现严重错误。

如果你确实需要这个,你可能应该GlobalInitializer在 的构造函数中调用bar_,但最好的方法是重新考虑你的设计。

于 2011-10-20T11:26:42.880 回答
0

你所做的似乎违反了面向对象的价值观,因为你的类不合理地依赖于它们之外的东西;我建议重新设计您的课程以避免这种情况。

话虽如此,适合您的设计模型而不使每个类都继承另一个的选项是将 MyInitializer 类创建为单例对象,并向依赖于此初始化的每个类添加 MyInitializer 。单例只会在它第一次被实例化时执行它的初始化。

于 2011-10-20T11:24:04.660 回答
0

大概你可以重构任何GlobalInitializer初始化为不再是全局的。然后,您可以选择如何为您的班级提供这些数据。你知道,因为全局变量很糟糕

于 2011-10-20T11:25:44.580 回答
0

梦到我:把bar_改成指针:

class Foo {
  public:
    Foo()
    {
      GlobalInitializer();
      // now we can call GlobalInitializer() in time
      bar_ = new Bar; 
    }
    ~Foo()
    {
      delete bar_;
    }

  private:
    Bar* bar_;
};
于 2011-11-17T20:33:05.453 回答