Search code examples
c++arraysconstructor

Object array initialization without default constructor


#include <iostream>
class Car
{
private:
  Car(){};
  int _no;
public:
  Car(int no)
  {
    _no=no;
  }
  void printNo()
  {
    std::cout<<_no<<std::endl;
  }
};
void printCarNumbers(Car *cars, int length)
{
    for(int i = 0; i<length;i++)
         std::cout<<cars[i].printNo();
}

int main()
{
  int userInput = 10;
  Car *mycars = new Car[userInput];
  for(int i =0;i < userInput;i++)
         mycars[i]=new Car[i+1];
  printCarNumbers(mycars,userInput);
  return 0;
}    

I want to create a car array but I get the following error:

cartest.cpp: In function ‘int main()’:
cartest.cpp:5: error: ‘Car::Car()’ is private
cartest.cpp:21: error: within this context

is there a way to make this initialization without making Car() constructor public?


Solution

  • Nope.

    But lo! If you use std::vector<Car>, like you should be (never ever use new[]), then you can specify exactly how elements should be constructed*.

    *Well sort of. You can specify the value of which to make copies of.


    Like this:

    #include <iostream>
    #include <vector>
    
    class Car
    {
    private:
        Car(); // if you don't use it, you can just declare it to make it private
        int _no;
    public:
        Car(int no) :
        _no(no)
        {
            // use an initialization list to initialize members,
            // not the constructor body to assign them
        }
    
        void printNo()
        {
            // use whitespace, itmakesthingseasiertoread
            std::cout << _no << std::endl;
        }
    };
    
    int main()
    {
        int userInput = 10;
    
        // first method: userInput copies of Car(5)
        std::vector<Car> mycars(userInput, Car(5)); 
    
        // second method:
        std::vector<Car> mycars; // empty
        mycars.reserve(userInput); // optional: reserve the memory upfront
    
        for (int i = 0; i < userInput; ++i)
            mycars.push_back(Car(i)); // ith element is a copy of this
    
        // return 0 is implicit on main's with no return statement,
        // useful for snippets and short code samples
    } 
    

    With the additional function:

    void printCarNumbers(Car *cars, int length)
    {
        for(int i = 0; i < length; i++) // whitespace! :)
             std::cout << cars[i].printNo();
    }
    
    int main()
    {
        // ...
    
        printCarNumbers(&mycars[0], mycars.size());
    } 
    

    Note printCarNumbers really should be designed differently, to accept two iterators denoting a range.