tags:

views:

2314

answers:

6

I have a class that contains an array. I want this array to be set at the length of a constant:

// Entities.h
    class Entities
    {
        private:
         const int maxLimit;
         int objects[maxLimit];
         int currentUsage;

        public:
         Entities();

         bool addObject(int identifier);
         void showStructure();
    };

The main problem I'm having is with the constructor. I thought:

// Entities.cpp
    Entities::Entities() : maxLimit(50)
    {
        currentUsage = 0;
        cout << "Entities constructed with max of 50" << endl;
    }

would have been sufficient...but not so. I don't know if I can use the initialiser list for array initialisation.

How can I initialise the 'objects' array using the 'maxLimit' const? I'm relatively new to classes in C++ but I have experience with Java. I'm mainly testing out this phenomenon of 'constness'.

Cheers.

+1  A: 

to dynamically allocate the memory you may need to use the 'new' keyword like

objects would be defined like:

int * objects;

inside the constructor you would do:

objects = new int [maxLimit];

edit:

forgot to mention, you'll need to deallocate the array when you're done, probably in the destructor of the class.

delete[] objects;
John Boker
Better include a copy constructor and operator=(), or an accidental copying will cause the destructor to be invoked twice. (E.g. delete[] on same pointer twice.) (Or you could make the class uncopyable.)
Mr.Ree
...and even better to use std::vector<int> objects; objects.resize(maxLimit); and skip both assignment operator and destructor worries.
Johann Gerell
A: 

const ints have to be initialized at declaration. If you don't know the value that it has to be at the time of declaration, you're going to have to adopt a different strategy.

You'll need to create the array in the constructor, while keeping a pointer outside. Is this what you want to do?

In your class :

private:
    int maxLimit;
    int* objects;

And outside:

Entities::Entities() : maxLimit(50)
{
    currentUsage = 0;
    cout << "Entities constructed with max of 50" << endl;
    objects = new int[maxLimit];
}

Entities::~Entities()
{
    delete [] objects;
}
sykora
Mr.Ree
You can't initialize them at the point of declaration, BTW (static consts you could initialize).
MSalters
+7  A: 

The array must have a constant length. I mean a length that is the same for all objects of that class. That is because the compiler has to know the size of each object, and it must be the same for all objects of that particular class. So, the following would do it:

class Entities
{
    private:
            static const int maxLimit = 50;
            int objects[maxLimit];
            int currentUsage;

    public:
            Entities();

            bool addObject(int identifier);
            void showStructure();
};

And in the cpp file:

const int Entities::maxLimit;

I prefer to use an enumeration for that, because i won't have to define the static in the cpp file then:

class Entities
{
    private:
            enum { maxLimit = 50 };
            int objects[maxLimit];
            int currentUsage;

    public:
            Entities();

            bool addObject(int identifier);
            void showStructure();
};

If you want to have a per-object size of the array, then you can use a dynamic array. vector is such one:

class Entities
{
    private:
            const int maxLimit;
            std::vector<int> objects;
            int currentUsage;

    public:
            Entities();

            bool addObject(int identifier);
            void showStructure();
};

// Entities.cpp
Entities::Entities(int limit) 
    : maxLimit(limit), objects(limit), currentUsage(0)
{
    cout << "Entities constructed with max of 50" << endl;
}

Best is to do as much initialization in the initialization list as possible.

Johannes Schaub - litb
+1 for the enum tip, its normally the best "hack" around static integers
Robert Gould
+1 This solves his problem without using dynamic memory, which means it's better than any other suggestion made so far (in terms of answering the spirit of his question).
Brian
As an aside, a private maxLimit member would be redundant if you are using a vector.
Brian
Brian, if the size of the vector is specified at runtime, doesn't that mean the memory it allocates is actually going to be from the heap? Or is vector somehow smart enough to expand itself on the stack?
Joseph Garvin
Joseph, well the vector solution get memory from the heap. the first two ones allocate without heap. c++1x will have std::dynarray for exactly this purpose: determine length at runtim, but still have a constant length (i.e not changing length), and when possible allocate from stack.
Johannes Schaub - litb
Joseph: True that maxLimit is pointless with a vector, but I was assuming he wanted a maxLimit for consistency, and that the vector would be pre-allocated. But vector has a member that will return its size already.
Brian
yes, i think so too. it's redundant for the array solution too. but i think consistency is more important here.
Johannes Schaub - litb
+5  A: 

You can use template argument if you need to set array size at compile time:

template<size_t maxLimit>
class Entities
{
    int objects[maxLimit];
    public:
        Entities() {}
        ...
};

Entities<1000> inst;
Lazin
But this would mean making the class body visible for all clients.
xtofl
Huh. The class body is _always_ visible to all clients, what's your point ?
A: 

If all objects have the same length, then length can be static. This makes it a constant integral expression allowed as an array bound:

class Entities
{
    private:
        static const int maxLimit = 50;
        int objects[maxLimit];
        int currentUsage;
    //...
};

Remember that sizeof(Entities) is a valid expression. Each Entities object has that same size.

MSalters
A: 

Use std::vector and you get the expected behaviour. No need to worry about pointers, copies, etc

#include <vector>

class Entities
{
private:
  const int limit;
  std::vector<int> objects;

public:
  Entities(int a_limit)
    : limit(a_limit), objects(a_limit)
  { }

  void addObject(int identifier)
  {
    if (objects.size() == limit)
      throw whatever;
    objects.push_back(identifier);
  }
};
Benoît