简体   繁体   中英

How to call parameterized constructor of member object variable in a class' default constructor in C++?

I want to initialize member object variables in the default constructor of the class.

Let's consider the following,

class ABC {    
    ABC(int A, int B) {
        a = A;
        b = B;
    }

    int a;
    int b;
};


class Foo {
    Foo();

    ABC m_obj1;
};

From the above example, I would like to initialize "obj1" in "Foo::Foo()". One of the restrictions I have is that I cannot do so in the initializer list, as I need to do some computation before I could initialize the member. So the option available (ASFAIK) is to do so in the body of the default constructor only.

Any inputs, how could I do this? Edit: Restricting to C++11

Would this be a correct way,

Foo:Foo() {
    int x = 10;
    int y = 100;

    m_Obj1(x, y);     //Is this correct? <--------
}

Depending on your exact problem and requirements, multiple solutions might be available:


Option 1: Use a function to do the computations and call Foo constructor

Foo makeFoo()
{
    // Computations here that initialize A and B for obj1 constructor
    return Foo(A, B)
}

Option 2: Call a function that does the computations and initialize obj1 in Foo member initializer list

ABC initABC() {
    // Some computations
    return ABC(A, B)
}

Foo() : obj1(initABC()) {}

Option 3: Dynamically allocate obj1, for instance with a std::unique_ptr


Option 4: Use std::optional or an emulated c++11 version as shown by other answers

You simply call the base constructor inside the initializer list of the derived constructor. The initializer list starts with ":" after the parameters of the constructor. See example code!

There is no problem to call functions inside the initializer list itself.

int CallFunc1(int x) { return x*2; }
int CallFunc2(int y) { return y*4; }

class ABC {
    public:
        ABC(int A, int B):a{CallFunc1(A)},b{CallFunc2(B)} {
            std::cout << "Constructor with " << a << " " << b << " called" << std::endl;
        }
    private:

        int a;
        int b;
};




class Foo {
    public:
    Foo(): obj1(1,2){}
    Foo( int a, int b): obj1(a, b){}

    private:
    ABC obj1;
};

int main()
{
    Foo foo;
    Foo fooo( 9,10);
}

edit:

The best method I can think of for your case is a copy constructor, being more specific on what you need to store helps a lot since if it is just two ints inside a class dynamic allocation is not worth it, the size of the object being constructed makes a difference to what method is best, copy constructors can be slower with much larger data types as the object has to be created twice: once when it is automatically constructed in the parent objects constructor and again when a temporary object is created and all the values have to be copied, which can be slower then dynamically allocating if the size is larger.

  1. As far as I'm aware all objects in a class are automatically initialized/allocated in the constructor so sadly dynamic memory use may be your best bet here.

  2. If you are fine with having the object initialized but empty so you know it is not 'ready' yet you can later fill it with useful data when you would have wanted to initialize it. This can be done with default constructors that set the things inside the object to null values or something similar so you know the object hasn't been properly initialized yet. Then before using the object you can check whether it has been initialized by checking for the null values or by having put a bool in the object that tells you whether it is initialized. Dynamically allocated would still be better in my opinion and makes the code look cleaner overall as all you need to store is a null pointer until the object is needed and then allocated and set to the pointer. It is also very easy to check if the pointer is equal to nullptr to know the state of your object.

Dynamically allocating memory may be a hassle since you have to make sure to get rid of memory leaks and it is slightly slower than using the stack, but it is a necessary skill for c++ since the stack is not enough when making programs that use more than the few available megabytes of data on the stack so if you are doing this simply to avoid the hassle I recommend learning it properly. It would be nice if you could be more specific about what kind of object you want to do this with or if you just want an answer that works for most cases. eg:

*ABC obj1 = nullptr;
...object is needed
obj1 = new(ABC(constructor stuff));
...obj1 isn't needed
delete obj1;

or c++ automatically deletes it when the program closes.

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