1

I have really been struggling with a piece of code for a couple days. The error message i receive when i run my code is: error: array initializer must be an initializer list accountStore (int size = 0) : accts(size) { }

There seem to be others with similar problems here but unfortunately I am unable to apply their solutions (either don't work or not applicable).

What I am simply attempting to do is create a container class (array, can't use vectors) of a class 'prepaidAccount' but I am just unable to get the constructor portion of the container class 'storeAccount' to work. See code snippet below:

    class prepaidAccount{
public:
    //prepaidAccount ();
    prepaidAccount(string newPhoneNum, float newAvailBal) : phoneNumber(newPhoneNum), availableBalance (newAvailBal){} //constructor 

    double addBalance(double howMuch) {
        availableBalance = howMuch + availableBalance;
        return availableBalance;
    }
    double payForCall(int callDuration, double tariff) {
        callDuration = callDuration/60;     //convert to minutes
        double costOfCall = callDuration * tariff;
        if (costOfCall > availableBalance) {
            return -1;
        }
        else {
            availableBalance = availableBalance - costOfCall;
            return costOfCall;
        }
    }

    void setAvailBal(int newAvailBal) {availableBalance = newAvailBal;}
    float getAvailBal() {return availableBalance;}
    void setPhoneNum(string newPhoneNum) {phoneNumber = newPhoneNum;}
    string getPhoneNum() const {return phoneNumber;}
private:
    string phoneNumber;
    float availableBalance;
};

    class accountStore { //made to store 100 prepaid accounts
        public:
               accountStore (int size = 0) : accts(size) { }
                  ....
        private:
              prepaidAccount accts[100]; 
}

In main I simply call accountStore Account;

Any help is absolutely welcome. I very recently started learning c++ and about classes and constructors so please bear with me.

Thanks

6
  • 1
    Change the definition of accts to std::vector<prepaidAccount> accts; and it should work. Commented Feb 24, 2016 at 8:21
  • prepaidAccount accts[100] calls a default constructor and since on doesn't exists, it fails on accountStore(int size=0) : accts(size) { } Commented Feb 24, 2016 at 8:22
  • 1
    what do you not understand? an array needs to be initialised with a list of constructors for its elements, not a size. and that's what the error says. arrays cannot have runtime-variable lengths. you must choose the size in the declaration, not the constructor. so, you've declared that the size is 100, but then you try to construct the array with a runtime-variable size. which is it, really? Commented Feb 24, 2016 at 8:22
  • Why do you think you cannot use a vector? Do you actually really need exactly 100 accounts, or might the number vary? If the latter, then you should use a container whose length can vary, of which vector is the usual default. Using a fixed-size array and picking some size you hope is big enough for all cases is a real anti-pattern, for various reasons, including the one you're reporting right now. Commented Feb 24, 2016 at 8:30
  • 1
    Anyway, if you absolutely must use a fixed-size array, then you either need to reenable your contained class's default constructor and use some kind of 'init() function' to make the elements valid after construction, or you need to supply a llist of arguments to construct all 100 of its elements in the container's initialiser list. There's no other way around this. (Assuming you really cannot use a vector...) Commented Feb 24, 2016 at 8:32

2 Answers 2

1
  1. You can't initialize an array with int like accountStore (int size = 0) : accts(size) {}.

  2. prepaidAccount doesn't have a default constructor, you have to write member initialization list like,

    accountStore (int size = 0) : accts{prepaidAccount(...), prepaidAccount(...), ...} { }

The array has 100 elements, it's not a practical solution here.

As a suggestion, think about std::vector, which has a constructor constructing with the spicified count of elements with specified value. Such as,

class accountStore {
    public:
        accountStore (int size = 0) : accts(size, prepaidAccount(...)) { }
              ....
    private:
        std::vector<prepaidAccount> accts; 
};
Sign up to request clarification or add additional context in comments.

4 Comments

surely you could also write accts{ {acct0args...}, {acct1args...}, ...}, which would be tidier (and i don't know if it helps promote copy elision?)
@underscore_d For the std::vector version too? I don't think it's a good idea...
and why do you think it's a bad idea?
Many thanks for the input @songyuanyao. Your answer actually works for me. The specs does not allow me to use vectors unfortunately. Your answer is precise and well received; much appreciated.
0

Given that you have specified that you do not want to use a container such as std::vector but would like to specify the size at runtime, your only option would be to manually implement dynamic allocation yourself. Also given that you are wanting create 100 objects at a time, I would suggest making a function that can construct a temporary object according to your needs and then use this to initialise your dynamically allocated array. Consider the below code as a good starting point. (WARNING untested code.)

class prepaidAccount {
 public:
  // Constructor
  prepaidAccount(string newPhoneNum, float newAvailBal)
      : phoneNumber(newPhoneNum), availableBalance(newAvailBal) {}
  // Default Constructor needed for dynamic allocation.
  prepaidAccount() {}

  /* your code*/
};

// Used to construct a tempoary prepaid account for copying to the array.
// Could use whatever constructor you see fit.
prepaidAccount MakePrepaidAccount(/*some parameters*/) {
  /* Some code to generate account */
  return some_var;
}

class accountStore {
 public:
  // Explicit constructor to avoid implicit type-casts.
  explicit accountStore(const int &size = 0)
      : accts(new prepaidAccount[size]) {
    for (int i = 0; i < size; i++) {
      // Will call defualt assignment function.
      prepaidAccount[i] = MakePrepaidAccount(/*some parameters*/);
    }
  }

  // Destructor
  ~accountStore() {
    // Cleans up dynamically allocated memory.
    delete[] prepaidAccount;
  }

  prepaidAccount *accts;
};

Edit: Amongst the c++ community it is often questionable when choosing to use dynamic allocation when there is such an excellent and comprehensive library of smart pointers. For example an std::vector would be perfect in this situation.

4 Comments

I would first check whether the OP's rationale for not wanting to use std::vector is actually valid, rather than having them reinvent the wheel, with all the pitfalls that entails, to ultimately achieve the same thing in a non-standard way.
@underscore_d I generally try to answer the question as asked... I do agree that a 'std::vector' would be far better suited. however I think that reinventing the wheel is sometimes important in understanding what the wheel is. :-) taking this feedback into account I will improve upon my answer.
Of course, and it's a good answer on that basis. Just I think, especially with new programmers, we're often better to check whether they really want what they think they want. :-)
Thanks for the help @bruffalobill. I actually received a suitable answer, but I am currently implementing this to see if I could make it work as well. Also, thank you for answering based on what my question requested, I knew I needed a solution that did not use vectors and as such I asked for that. Thanks again, much appreciated.

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.