undeclared identifier using class compared to main function - c++

I want to understand why I receive a syntax error for the same syntax in different code areas.
For example:
#include<iostream>
class Grading
{
public:
Grading();
~Grading();
private:
//Here syntax is broken
//reason: undeclared Identifier
const int studentID = 50;
int students[studentID];
};
int main() {
//Here syntax is fine.
const int studentID = 50;
int students[studentID];
return 0;
}

const int studentID = 50; should be static const int studentID = 50;. Right now you are declaring studentID as a non-static class member and it will constructed (and assigned a value 50) only when class instance is constructed while to declare an array compiler requires array size to be known at compile time. Basically your code is equivalent to this:
class Grading
{
public:
Grading(): studentID(50) {}
~Grading();
private:
const int studentID;
int students[studentID];
};
If you write const int studentID = 50; outside of class scope (in main for example) then it would be just a regular constant with a value 50 known at compile time.

The size of a C++ member array must be a constexpr - known at compile time, simple const is not enough, since it will be initialized at runtime, when you create an instance of the class.
However, static const is enough, since you must initialize it with a constexpr, so the value is known at compile time.

Related

How do I setup an array in C++ with a constant as the max size allowed?

class grades
{
private:
char *grade;
string course[20];
int numCourse;
public:
grades();
bool setGrade(char *gradeIn);
bool setCourse(char *nameIn);
};
So that's my class declaration. I want to set a constant number instead of 20 in the array declaration. How would I go about doing that? I have tried static const but the problem is that every time the class returns an error saying out of scope.
This doesn't work?
class grades
{
private:
char *grade;
static const int MAX_COURSES = 20;
string course[MAX_COURSES];
int numCourse;
public:
grades();
bool setGrade(char *gradeIn);
bool setCourse(char *nameIn);
};
Use a #define. Old school, but it still works.
or... declare a
const int MAX_ARRAY_SIZE = 20
in a namespace (i.e. outside of the class).

variable-sized object may not be initialized

I have a class like this
class aClass
{
public:
aClass() : N(5) {}
void aMemberFunction()
{
int nums[N] = {1,2,3,4,5};
}
private:
const int N;
};
The testing code is
int main()
{
aClass A;
A.aMemberFunction();
const int N = 5;
int ints[N] = {5,4,3,2,1};
return 0;
}
When I compile (g++ 4.6.2 20111027), I get the error
problem.h: In member function ‘void aClass::aMemberFunction()’:
problem.h:7:31: error: variable-sized object ‘nums’ may not be initialized
If I comment out the line with int nums[N] I don't get a compilation error, so the similar code for the ints array is fine. Isn't the value of N known at compile time?
What's going on? Why is nums considered a variable-sized array? Why are the arrays nums and ints handled differently?
Isn't the value of N known at compile time?
No. At the time aMemberFunction is compiled, the compiler does not now what N is, since its value is determined at run-time. It is not smart enough to see that there is only one constructor, and assumes that the value of N could be different than 5.
N isn't known at compile time in your example, but it is in this one:
class aClass
{
private:
static const int N = 5;
public:
aClass() {}
void aMemberFunction()
{
int nums[N] = {1,2,3,4,5};
}
};
The above code will compile, and will declare a local array of five ints.

How to declare a constant array in class with constant class variable?

How to declare a constant array in class with constant class variable? Is it possible.
I don't want dynamic array.
I mean something like this:
class test
{
const int size;
int array[size];
public:
test():size(50)
{}
}
int main()
{
test t(500);
return 0;
}
the above code gives errors
No, it's not possible: As long as size is a dynamic variable, array[size] cannot possibly be implemented as a static array.
If you like, think about it this way: sizeof(test) must be known at compile time (e.g. consider arrays of test). But sizeof(test) == sizeof(int) * (1 + size) in your hypothetical example, which isn't a compile-time known value!
You can make size into a template parameter; that's about the only solution:
template <unsigned int N>
class Test
{
int array[N];
static const unsigned int size = N; // unnecessary really
public:
// ...
};
Usage: Test<50> x;
Note that now we have sizeof(Test<N>) == sizeof(int) * (1 + N), which is in fact a compile-time known value, because for each N, Test<N> is a distinct type.
You mean a fixed sized array? You could use std::array like this:
#include <array>
class test
{
static const size_t s_size = 50;
std::array<int, s_size> m_array;
public:
test()
{
}
};
Or if you want to support different sizes you need to resort to a class template like this:
#include <array>
template <size_t SIZE>
class test
{
std::array<int, SIZE> m_array;
public:
test()
{
}
};
std:array has the added benefit of keeping the size information along with the member (unlike arrays which decay to pointers) and is compatible with the standard library algorithms.
There is also a version that Boost offers (boost::array) which is similar.
Your code yields an error because compiler needs to know the size of data type of each member. When you write int arr[N] type of member arr is "an array of N integers" where N must be known number in compile time.
One solution is using enum:
class test
{
enum
{
size = 50
};
int arr[size];
public:
test() {}
};
Another is declaring size as static const member of class:
class test
{
static const int size = 50;
int arr[size];
public:
test(){}
};
Note that in-class initialization is allowed only for static class integers! For other types you need to initialize them in code file.

Multiple instances of a class with constant variables use same memory for constants?

If I have a class that defines multiple constant variables like so...
class SomeClass {
public:
SomeClass() : SOME_CONSTANT(20), ANOTHER_CONSTANT(45), ANOTHER_CONSTANT2(25), ANOTHER_CONSTANT2(93) { }
private:
const int SOME_CONSTANT;
const int ANOTHER_CONSTANT;
const int ANOTHER_CONSTANT2;
const int ANOTHER_CONSTANT3;
Will multiple instances of this class be optimized to point to the same memory for the constants? or can I save memory by making each constant static?
If they are not static, then no, they will not be optimized out. Each instance will have space for all the constants. (In fact, I don't think the compiler is even allowed to combine them in any way.)
If you do declare them static, they are in global memory and not in each instance. So yes, it will use less memory.
EDIT:
If you want to make them static constants, it should be done like this:
class SomeClass {
public:
SomeClass(){ }
private:
static const int SOME_CONSTANT;
static const int ANOTHER_CONSTANT;
static const int ANOTHER_CONSTANT2;
static const int ANOTHER_CONSTANT3;
};
const int SomeClass::SOME_CONSTANT = 20;
const int SomeClass::ANOTHER_CONSTANT = 45;
const int SomeClass::ANOTHER_CONSTANT2 = 25;
const int SomeClass::ANOTHER_CONSTANT3 = 93;
How about an enumeration instead?
class SomeClass {
public:
SomeClass() { }
private:
enum {
SOME_CONSTANT = 20,
ANOTHER_CONSTANT = 45,
ANOTHER_CONSTANT2 = 25,
ANOTHER_CONSTANT3 = 93
};
};
An enumeration guarantees that the constants won't take up any memory at all.
Declared this way, all instances of this class will have its own copies. To avoid this and save memory, declare them as static.
Note: don't forget to define them outside the class. As these are ints, you may avoid defining them outside the class, this actually depends more on the compiler, than the standard (yes, I know how ridiculous this soudns). I can't test it now, but I remember, that gcc and VS have different behaviors about this.
So, you may need to do this:
class SomeClass {
public:
SomeClass()
{ }
private:
static const int SOME_CONSTANT;
static const int ANOTHER_CONSTANT;
static const int ANOTHER_CONSTANT2;
static const int ANOTHER_CONSTANT3;
const int SomeClass::SOME_CONSTANT = 20;
//.. the same for the others.
EDIT I'll find this part of the standard (the exception for integral types) and post it here + tests on both compilers later today :) )
You cannot make those constants static - simply because your constructor initialses them!
SomeClass() : SOME_CONSTANT(20), ANOTHER_CONSTANT(45), ANOTHER_CONSTANT2(25), ANOTHER_CONSTANT2(93) { }
Remove those initialisers i.e.
SomeClass{};
static const int SOME_CONSTANT = 20;
Then you will have just one int for the class.
You can try checking the sizeof() of an instance of the class. I don't think they'll be optimized out. Using const static variables for this purpose will probably be the right thing to do, especially if they are all integers, in which case you can initialize them at the definition and get compile time constants without worrying about static objects initialization order.
class SomeClass
{
private:
const static int SOME_CONSTANT = 20;
const static int ANOTHER_CONSTANT = 45;
const static int ANOTHER_CONSTANT2 = 25;
const static int ANOTHER_CONSTANT3 = 93;
};

C++ Array Member of Constant Length (Initialisation of)

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'.
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.
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;
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;
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;
}
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.
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);
}
};