C++重构:构造函数中的初始化顺序

发布于 2024-12-11 00:34:08 字数 833 浏览 0 评论 0原文

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

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

在 Foo 中调用 GlobalInitializer() 已经太晚了,因为我需要在 bar_ 初始化之前调用它。我对此的解决方法是创建一个超类:

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 的实例)。

Suppose I need to call a free GlobalInitializer() before my constructor initializes any member variables. For example:

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

Calling GlobalInitializer() in Foo is too late because I need to call it before bar_ is initialized. My hacky work around for this has been to create a super-class:

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

UglyFoo gets the job done, but it requires this ugly MyInitializer class. Is there a cleaner design pattern or refactoring which will achieve the same result?

Additional Note: GlobalInitializer() is an expensive call that I want to avoid unless the user instantiates a Foo(). There are guards inside GlobalInitializer() against multiple calls. Also, there may be other classes, say FooBar, that also need to call GlobalInitializer(), but in one process, GlobalInitializer() will actually do work once (if Foo or FooBar is instantiated) or not even once (if there are no instantiations of Foo or FooBar).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

请持续率性 2024-12-18 00:34:08
class Foo {
private:
    struct Initializer {
        Initializer() { GlobalInitializer(); }
    };
    Initializer initializer__;  // declare before bar__ to ensure it is constructed first

public:
    Foo() : bar_()
    {
    }

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

public:
    Foo() : bar_()
    {
    }

    Bar bar_;
};
帝王念 2024-12-18 00:34:08

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

好的设计意味着松耦合。如果您的对象创建依赖于不同的方法调用来工作,则存在严重错误。

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

You should probably re-think your design.

A good design implies loose-coupling. If your object creation depends on a different method call to work, there's something seriously wrong there.

If you do need this, you should probably call GlobalInitializer inside the constructor of bar_, but the best way to go about this is re-thinking your design.

深巷少女 2024-12-18 00:34:08

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

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

What you're doing seems to violate object oriented values as your classes are unreasonably dependent on something outside them; I would recommend redesigning your classes to avoid that instead.

That being said, an option that fits your design model without making each class inherit another is to create the MyInitializer class as a singleton object, and add a MyInitializer to each class that depends on this initialization. The singleton will only perform its initialization the first time it gets instantiated.

看透却不说透 2024-12-18 00:34:08

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

Presumably you could refactor whatever GlobalInitializer initializes to not be global anymore. Then your options open up on how to give your class that data. You know, because globals are bad and all.

黑凤梨 2024-12-18 00:34:08

我在梦中遇到过:将 bar_ 更改为指针:

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

  private:
    Bar* bar_;
};

Came across to me in a dream: change bar_ into a pointer:

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

  private:
    Bar* bar_;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文