简体   繁体   中英

Calling function before objects are created in a class

Basically, I have one class that owns another object:

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

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

and for 'B' to function, the init systems function needs to be called in A. Is there any 'nice' way to work around this? Like creating the 'B' object later or something?

Sounds like your classes are too tightly coupled . There's many ways to fix this, but it depends on the rest of your design.

Maybe A shouldn't own a B, since A is a dependency of B. You could inject an instance of A into each B as they get instantiated.

Maybe B shouldn't exist and all, and it should be merged into A:

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

It's my opinion that most initialization methods are code smells (that is, it suggests a bad design). Some people have given this pattern a name: "Design Smell: Temporal Coupling"

If you desire to keep the B a regular member of A, the two places you can run code before the construction of b are:

  1. the constructor of a base class of A,
  2. in the initializer list of a member of A, for a member declared above b .

If you wish to defer construction of the B, you need to hold the object by indirection or later construct it onto raw storage and when destroying, perform placement destruction.

Most of this has strange smells to it, it may be beneficial to reorganize your code to avoid this kind of structure.

You simply need to change your design so initSystems() is requirement for both A and B .

If you can't do this (although you really should), there are other ways, like dynamic allocation:

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

I agree with @nanny over the decoupling of the class and merging if possible.

But your scenario seems like in which B is separate entity in your system, hence a class. And A contains a B , hence the composition.

So one way of solving this would be, you keep a reference (pointer) to B in A instead of making B a part of A.

Or you should not access the stuff that is created in initInstance() of A in the constructor of B, and create a method postConstruct in B that you can call from A after call initInstance. Following code explains it,

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 
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM