1

Using VS2012, I have encountered an unprecedented problem, my main class have a member, which is a an array of another small class. This small class has an explicit constructor. Now the problem: How to supply the initialization list?

The following is the code:

class A { //This is the small class
private:
    int value;
public:
    explicit A(int newNumber) {
        value = newNumber;
    }
};

class B {//This is the major class
private:
    A arrayOfA[5];
public:
    B() {//Compiler complain "no default constructor for class A"
         //But I really don't know how to supply the initialization list
    }
};

Thanks a lot!

4 Answers 4

4

With a constructor initializer list:

B() : arrayOfA{A(1), A(2), A(3), A(4), A(5)} {}

I would also suggest changing the array to a std::array. If this is not C++11, I'm afraid you cannot initialize your member without having a default constructor for A. However, there is still the possibility of making your own (it's not hard) or using boost::array. In such a case, I am not sure whether it is possible to initialize the array directly, but it definitely is with a helper function.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 but I'm pretty sure VS2012 will not accept this. It might work if he has the CTP installed.
@Praetorian, I believe it will only work with the CTP, but then VS2013 is a better option anyway. That's a good point, though, which I guess makes the pre-C++11 advice more relevant. I can't remember whether VS2012 has std::array, or frankly whether it would work by using ({{A(1), ...}}) or something without the brace initialization syntax.
Thanks a lot! I learned this syntax in a C++ book I have bought, but wonder why it never worked. Seems that It is not supported in VS2012. In the end, I used the default constructor. Maybe time to upgrade to VS2013.
2

One way to resolve this is to provide a default constructor in A.

class A {
private:
    int value;
public:
    A() : value(0) {}

    explicit A(int newNumber) {
        value = newNumber;
    }
};

2 Comments

An alternative that avoids accidental implicit use of such a default constructor is to add a placeholder argument e.g. enum Uninitialised { uninitialised }; A(Uninitialised) { } - here I'm also avoiding the value = 0 given the caller's intent to assign to the variable later....
Yes... that's an orthogonal design decision, but done as and for reasons it explains it the comment. Sometimes it's useful to avoid initialisation - especially when creating a large array that you'll soon assign meaningful values to.
0

I suggest that you initialize all values of the array to 0 with a default constructor and then use a setter function that accepts 2 params to deal with manipulating the array:

A::setVal(int val)
{
    value = val;
}

B::setA(int index, int value)
{
    arrayOfA[index]->setVal(value);
}

Something like that should work.

Comments

0

This is a workaround for non-default-ctors not being useable here pre-C++11.

Just wrap your arrayOfA in an anonymous union. This means neither the constructors nor destructors will be called automatically. Use placement-new/delete. (Beware of automatically defined special member-functions though)

It would look like this:

class B {//This is the major class
private:
    union{A arrayOfA[5];};
public:
    B() {
        for(size_t i = 0; i < sizeof arrayOfA / sizeof *arrayOfA; i++)
            new((void*)&arrayOfA[i]) A(i);
    }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.