class Try {
const int no = 5;
int arr[no];
};
Here is a simple class , but I get this compilation error. no is constant so I thought it should not be the problem.
arr must have the same size in all instances of your class. no is const but that only means it never changes after an instance is created. It doesn't mean that it is the same for all instances all the time. For example, no can be set in the initializer list of the constructor
Foo::Foo(int size) : no(size)
{}
For this reason, unless you make no static, you can't use it as array size because that would imply potentially differently sized arrays in each instance.
Related
I need to instantiate many objects from a class, but each one of them needs to be aware of a certain value X that is common for every object of this class, like a global parameter. This is necessary for my constructors to work properly in my objects.
Is there a way to do that without passing the value as a constructor parameter? What I wanna do is use the same variable in all objects so I don't waste RAM.
*in my real situation it's not just an X value, is a 1024-dimmension int vector.
What you want is a static member. "When a data member is declared as static, only one copy of the data is maintained for all objects of the class". e.g.
class myClass {
public:
static int x;
};
I assume you mean that you want a vector of size 1024 as the shared variable across all your classes. You could do this:
class MyClass {
static std::vector<int> s_my_vector;
}
This code would go into your header file. In your cpp file, you'd have to initialize the std::vector. However, I do not recommend this. Class static variables that require constructor calls (i.e. not primitives or POD types) have a lot of gotchas that I'm not planning to go into. I will offer a better solution however:
class MyClass {
static std::vector<int> & GetMyVector()
{
static std::vector<int> my_vector;
static bool initialized = MyVectorInit(my_vector);
return my_vector;
}
static bool MyVectorInit(std::vector<int> & v)
{
v.resize(1024);
...
}
public:
MyClass() {
std::vector<int> & v = GetMyVector();
...
}
static void EarlyVectorInit()
{
GetMyVector();
}
}
In this case, the static local variable ensures that there will only be one copy of my_vector, and you can get a reference to it by calling GetMyVector. Furthermore, the static bool initialized is guaranteed to only be created once, which means that MyVectorInit will only be called once. You can use this method in case you need to populate your vector in some non-trivial way that can't be done in the constructor.
The way I've written it, your vector will be created automatically the first time you need to use it, which is fairly convenient. If you want to manually trigger creation for some reason, call EarlyVectorInit().
I would to initialize a const int member (numGrids) of my class TestCase when I construct a TestCase. It needs to be const (I think) because it defines the elements of another array member of the classwhich I would also like to initialize when I create a TestCase. The code is shown below:
/////////////////////////////////////////////////////////////////////////////////////
//TestCase.h
class TestCase
{
protected:
const int numGrids;
Grid meshes[numGrids];
public:
TestCase(const int);
};
/////////////////////////////////////////////////////////////////////////////////////
//TestCases.cpp
TestCase::TestCase(const int numGridsSpec)
{
numGrids = numGridsSpec;
Grid grids[numGrids];
}
I cannot seem to initialize the const member of my class. I need that member to be constant because it defines the array size of meshes. I get the following errors:
[ 12%] Building CXX object sources/CMakeFiles/GridRefinementStudy.dir/TestCase.cpp.o
In file included from /home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:16:0:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:5:12: error: invalid use of non-static data member ‘TestCase::numGrids’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:6:14: error: from this location
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:6:22: error: array bound is not an integer constant before ‘]’ token
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp: In constructor ‘TestCase::TestCase(int)’:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:25:1: error: uninitialized member ‘TestCase::numGrids’ with ‘const’ type ‘const int’ [-fpermissive]
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:28:13: error: assignment of read-only member ‘TestCase::numGrids’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:29:21: error: no matching function for call to ‘Grid::Grid()’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:29:21: note: candidates are:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:13:2: note: Grid::Grid(int, int, double, double)
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:13:2: note: candidate expects 4 arguments, 0 provided
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:1:7: note: Grid::Grid(const Grid&)
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:1:7: note: candidate expects 1 argument, 0 provided
make[2]: *** [sources/CMakeFiles/GridRefinementStudy.dir/TestCase.cpp.o] Error 1
make[1]: *** [sources/CMakeFiles/GridRefinementStudy.dir/all] Error 2
make: *** [all] Error 2
You may not do such a way. The size of the array shall be known at compile time. In fact you are trying to get a variable length array. C++ does not have such a feature.
Take into account that if the sizes of the array are different for two objects then the classes that define them are different types. They have different data members that is arrays with different sizes. The size of a class shall be the same for each object of that class.
I would suggest to use standard container std::dynarray if the compiler supports it or
std::vector
On the other hand you could define your class as a template class. For example
template <size_t numGrids>
class TestCase {
protected:
Grid meshes[numGrids];
//...
or even as
template <size_t numGrids>
class TestCase {
protected:
std::array<Grid, numGrids> meshes;
//...
I think that using a template class is the best approach in your case.
In pre-C++11, there are four ways of initializing a member:
If the member is static, const and has an integral type,
it can be initialized directly in the class definition. In this
case, the member is a "integral constant expression", and can be
used anywhere the compiler requires such (e.g. array dimensions,
template argument, etc.).
If the member is static, it must be initialized in its
definition. If the member is also const, it is a constant
expression in the translation unit which contains the
definition, after the definition.
Any member can be initialized in the initializer list, and
typically, all should be (but there are exceptions). Non-static
const members must be initialized here (but non-static const
members are not constant expressions, and cannot be used as
such).
Finally, non-const members can be "initialized" in the
constructor body. Formally, this is assignment, not initialization, and if
the member type has a user defined constructor, it will still be
initialized (using the default constructor) in the
initialization list. For primitive types, the member remains
uninitialized if it isn't mentionned in the initializer list,
until it is first assigned.
In your case, it would appear that you want an array whose size
is defined by a parameter to the constructor. This is not
possible; the size of an array must be an integral constant
expression. If the size should always be the same, then you can
use a static const int to define it:
class TestClass
{
static int const numGrids = 25;
Grid meshes[numGrids];
// ...
};
Otherwise, you'll have to use:
class TestClass
{
std::vector<Grid> meshes;
public:
TestClass( int size ) : meshes( size ) {}
};
This might be the better solution anyway.
First of all since numGrids is const in the class declaration, you can only initialize it through initialization list.
TestCase::TestCase(const int numGridsSpec)
:numGrids(numGridsSpec) // this is the initialization list
{
...
}
This is simply because a constant variable can only be set to a value once and can not be modified 'legally' thereafter, compilers normally would not allow you to proceed avoiding unexpected consequences in this case.
There's a mistake in your code. The array size is dynamic (a variable). You can't use a variable to declare an array size at compile time. Use some constants with real value.
To Answer your question
Initializer list is used to init the data for a const. Something as follows.
class TestCase {
protected:
const int numGrids;
public:
TestCase(const int x) : numGrids(x)
{
}
};
Solution for your problem
class TestCase {
protected:
const int numGrids;
Grid* pMeshes;
public:
TestCase(const int x) : numGrids(x)
{
pMeshes = new Grid[x];
}
~TestCase() : numGrids(x)
{
delete []pMeshes; // release allocated memory in destructor
}
};
int main(int argc, char* argv[])
{
TestCase t(10);
return 0;
}
If your compiler supports c++11, you could simply do:
class TestCase
{
protected:
const int numGrids = 25;
Grid meshes[numGrids];
public:
TestCase(const int);
};
I have a question regarding good design in C++. I have a class A, and all objects of this class use an integer array of constant values (they should share the same array, as their values are constant). The array needs to be computed (just once) before any object A.
I thought about having another class B which contains the integer array as a static member, an init() method which would fill this array according to some formula and a static boolean flag initialized (if this variable if true then the init() method would do nothing), but I'm not sure this is the best way to solve my design issue.
So my question is, what would be a good design/way to accomplish this ?
Thanks in advance.
Since the array is constant, use const.
Since the array is shared among all instances of the class, use static.
In your header file, declare it:
class A
{
static const int the_array[10];
}
In A's source file, initialize the one instance:
const int A::the_array[10] = { ... };
Edit from comment...
Or, if the array is better generated algorithmically, use a constant pointer. The usage syntax for the array would be the same.
Note that both the array and the pointer are const.
Header:
class A
{
static const int * const the_array;
}
Source file:
namespace
{
const int * generate_my_array()
{
// Allocate an array, initialize it, return it.
}
}
const int * const A::the_array = generate_my_array();
Hi I was trying to define a constant inside a class, doing it the normal or usual way doesnt seem to work
class cat
{
public:
cat();
~cat();
private:
static const int MAX_VALUE = -99999;
int Number;
public:
void OrganizeNumbers();
void SetNumbers();
};
So the solution I found after doing some research was to declare it as static but what does this means and also I want to ask it is really necesary to declare a constant, becuase as you can see it is private right? i means it can only be accessed by the class methods so why to set a constant and also I read that using static only allows you to use integral type so its actually a dissavantage... if you are thinking to make a game.
static means that the member will be shared across all instances of your object.
If you'd like to be able to have different values of a const member in different instances you'll need to use a initialization list to set it's value inside your constructor.
See the following example:
#include <string>
struct Person {
Person (std::string const& n)
: name (n)
{
// doing: 'name = n' here is invalid
}
std::string const name;
};
int main (int argc, char *argv[]) {
Person a ("Santa Claus");
Person b ("Bunny the Rabbit");
}
Further reading
[10] Constructors - parashift.com/cpp-faq
10.1 Construct Initialization List
Initialization Lists in C++
1) Declare it "private" if you're only going to use MAX_VALUE inside your class's implementation, declare it under "public" if it's part of your class's interface.
2) Back in "C" days, "static" was used to "hide" a variable from external modules.
There's no longer any need to do this under C++.
The only reason to use "static" in C++ is to make the member class-wide (instead of per-object instance). That's not the case here - you don't need "static".
3) The "const" should be sufficient for you.
4) An (older-fashioned) alternative is to define a C++ enum (instead of a "const int")
There seems to be some confusion of ideas here:
A static member doesn't have to be an integral type, the disadvantage you mention does not exist.
const and private are unrelated, just because a member can only be accessed from instances of a given class, doesn't mean that nothing is going to change it.
Being const-correct guards against runtime errors that may be caused by a value changing unexpectedly.
you have to init the const attribute in the constructor with :
cat() : MAX_VALUE(-99999) {}
(which was declare as const int MAX_VALUE;)
data member inside a class can be const but only if its static.
otherwise we need to have a constructor to initialize a constant inside a class.
can we declare a const data member inside a class? //this was an interview question
It seems to me that we can, but is it appropriate for a programmer to declare a constant inside a class.
please give some explanation/reasons, why we can or cannot do?
Off course you can :
struct A
{
A() : a(5)
{
}
const int a;
};
int main()
{
A a;
}
This means that the data member a, inside struct A is not going to change.
Short answer : You can have a non-static const member inside a class.
As you still need to assign it a value, the only place where you're allowed to is in the initialization list.
And, well, it's always a good reason to do it if your member is really constant. I mean, const-correctness is mainly an optional tool to help better coding, so use it if you want, you'll thank yourself later. And if you don't use it... well it doesn't really matter!
sure if you have some constants you want to use in your class, and belong to a class.
For example, lets say you have some data type with a unique ID, the ID identifies the object an therefor will never change:
class myData {
cont int ID;
myData(int newID) : ID(newID) {}
}