I've got a class, and part of the input into the class is a vector (called Data) of variable length (lets say it has length N). I've included this after the function:
N = data_->size();
In the private section of the class, I want to declare an array double A[N][N];. However, when I try to do this, I get something saying
error: "N is not a type name, static, or enumerator".
How do I create the array A[N][N]?
Sorry if this is already explained somewhere else, as I'm very new to c++, so wouldn't even know what to look for!
Edit -- attached code:
class foo {
public:
foo (std::vector &data)
: data(data_)
{
N = data_->size();
M = /* four times the last member of data (which is a vector of positive integers)*/
}
private:
double A[M][M];
void foo(void)
{
for (std::size_t i=1; i<=M; ++i)
{
A[i][i] = 1;
}
}
};
Hope that makes some sort of sense... How would I be able to define A[M][M]? Maybe it's not possible to do it for M as M is a function of the data. If not possible for M, is it possible for N?
One possibility I can think of is that I can make A a std::vector< std::vector<double> > A and then push a lot of 0's or something into it, and THEN modify the values...
if you´re using the std::vector class you must creates the vector in a function of the data_ class (like the constructor, for example), using this sentence:
A = vector<vector<double> >(N, vector<double>(N, 0));
The first parameter of the parentheses is the size of the vector and the second is the type of data on it.
Sorry for my english, i´m spanish and my english isn´t very good.
You cannot do that. Arrays are types, and they have to be known at compile time. This includes their sizes. So you cannot have a dynamic array as part of your class. The closest thing you get is a pointer to manually allocated array, but that is in fact essentially a std::vector. So perhaps the easiest solution is to just have a vector of vectors, or perhaps a single vector of size N * N that you access in strides j + N * i.
Example:
std::vector< std::vector<int> > v(N, std::vector<int>(N));
Or:
std::vector< std::vector<int> > v;
//...
v.resize(N, std::vector<int>(N));
Access: v[2][4] = 8;
Update: Since you edited your answer, you can write something like this to get you an N * 4n vector, where data.back() == n:
std::vector<unsigned int> data = get_data(); // given!
std::vector< std::vector<double> > v(data.size(), std::vector<double>(4 * data.back()));
Hmmm...several issues here...
Neither N nor M are declared (either in the constructor or as members of foo)
You are trying to initialize a member data that is not declared (and you may mean data_(data) as the syntax is member(expression), not expression(member))
The argument to your constructor is an incomplete type: it needs to be std::vector< sometype >; if you want it to be generic you'll need to use templates or get some help from boost
You are not initializing the only member variable that you have declared (A)
void foo(void) is a problem because it is not the correct syntax for a constructor (which has no type) but uses the class name
Let's build up to something closer to what you want
Start with a class foo:
class foo {
};
with a constructor taking a single argument of type std::vector<double>
class foo {
public:
foo(std::vector<double> &data);
};
you want to initialize a member variable with the data
class foo {
private:
std::vector<double> data_;
public:
foo(std::vector<double> &data)
:data_(data)
{};
};
At this point I'll note that I would generally not put the definition of a non-trivial constructor in the class declaration, but in a implementation file instead, and consequently I would be able to put the declaration of member variable beneath the public section with the declaration of the constructor. But for compactness I'll leave this way here.
You want to capture and store the size of the data
class foo {
private:
std::vector<double> data_;
size_t N;
public:
foo(std::vector<double> &data)
:data_(data)
,N(data.size())
{};
};
At this point we still haven't made that multi-dimensional storage that you want, but now you have some decisions to make about how to manage the storage. If you use Kerrek SB's approach this looks something like
class foo {
private:
std::vector<double> data_;
size_t N;
std::vector< std::vector<double> > A;
public:
foo(std::vector<double> &data)
:data_(data)
,N(data.size())
,A()
{
A.resize(N);
for (size_t i=0; i<N; ++i) {
A[i].resize(N);
}
};
};
You need to create it dynamically, using a smart pointer if you do not want to manage memory yourself.
double **A;
in the constructor:
A = new double *[N];
for(i=0;i<N;++i)
{
A[i] = new double [N];
}
Not that you have to call delete in your destructor and now to obey the rule of three you have to have a copy constructor and a assignment operator... Using a smart pointer is better here: see the Boost smart pointer help page.
Related
I was wondering if it was possible to create an array of objects when the object needs things passed into it for the constructor. I want something like this:
MyClass *myVar;
myVar = new MyClass[num]; // I would like to specify the array size after declaration
int i = 0;
for(i = 0;i < num;i++)
myVar[i] = new MyClass(0,0); // I would also like to populate the array with new objects
I know that this works:
MyClass *myVar;
myVar = new MyClass[num];
but this only works when the constructor has nothing passed into it. Is what I am trying to do possible? If so, how do I do it?
EDIT: I found out how to do it with using arrays. Here is how I did it:
MyClass **myVar;
myVar = new MyClass *[num];
for(i = 0;i < num;i++)
myVar[0] = new MyClass(0,0);
I would use vectors and such but my teacher has told us to use basic arrays whenever possible. The above solution I actually got from some code my teacher wrote. Thank you all for your help!
MyClass *myVar;
myVar = new MyClass[num];
Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.
However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:
#include <vector> //header file where std::vector is defined
std::vector<MyClass> arr(num, MyClass(10,20));
It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.
The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:
arr.push_back(MyClass(20,30));
And now you can access elements, just like you access array, i.e by using index:
f(arr[i]); // 0 <= i < arr.size();
Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:
#include <algorithm> //header file where std::for_each is defined
std::for_each(arr.begin(), arr.end(), f);
where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.
In C++11, you can use lambda as:
std::for_each(arr.begin(), arr.end(), [](const MyClass & m)
{
//working with m
});
In C++0x, this grammar works, which can call the non-default constructor in new expression:
MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};
But I doubt if it works when the number of elements in available only at run time.
The vector approach would be better, as shown in Nawaz's answer.
Pointer to pointer is equivalent to 1. array of pointers, and 2. vector<T*> vector of pointers. One way I've done this in the past is using a double pointer. This approach eliminates the overhead of vector data structure and preferred memory efficient is needed.
MyClass ** myvar;
myvar = new Myclass*[num]
for(int i = 0; i < num; i++){
*(myvar+i) = new Myclass(i);}
Works with pretty much any control structure you can imagine. The drawback is that the allocation of memory is not contiguous and my affect speed for large number of num.
You can do something like this too:
MyClass *myVar[num];
for(int i = 0; i < num; i += 1)
{
myVar[i] = new MyClass(0, 0);
}
Actually, you can use a placement new to handle this:
MyClass * myVar;
myVar = reinterpret_cast<MyClass *>(new char[num * sizeof(MyClass)]);
int i = 0;
for (i = 0; i < num; i++) {
new(&myVar[i]) MyClass(0,0);
}
#Nawaz answer is really good about using vectors, but didn't work for me because it create vector of the same objects (all of them reference to the same object)
class Graph
{
public:
Graph(long V); // none default Constructor
}
std::vector<Graph> myGraph;
for (int i = 0; i < T; i++) // read all graphs
{
Graph newGraph(N);
myGraph.push_back(newGraph);
}
In my platformer game which I'm writing in Visual C++, each level will initially be stored as a 2-dimensional array of ints. I decided it would make more sense to store this array in a class, so I created a class called Level. It looks like this:
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
map = a;
}
int getcell(int row, int column) {
return map[row][column];
}
};
As far as I can see - from looking up tutorials on class constructors, and passing 2-dimensional arrays as parameters, this should work, so I really don't understand why it doesn't.
On the line where I do map = a, I get an error: Error: expression must be a modifiable lvalue. I've looked this error up on stackoverflow, but I can't find any answers which relate to my problem.
So, how can I fix this error?
This doesn't really have anything to do with a constructor. You cannot assign arrays in C++. Whether in the constructor, or anywhere else.
There are two ways to work around it. The first way is the brute force way. Instead of
map = a;
write a loop to copy the contents of the array from the constructor's parameter into the class member array.
The second way is to stuff the array into an intermediate class:
class Level {
public:
struct level_map {
int map[20][30];
};
private:
level_map map;
public:
Level(const level_map &initial_map) : map(initial_map)
{
}
int getcell(int row, int column) {
return level_map.map[row][column];
}
};
This may or may not be practical, and introduces a little bit more complexity.
But the real answer here is to use std::vectors instead of plain arrays, which will solve all of these problems.
Others have already mentioned the real reason: you cannot assign an array to another using = operator. My two cents about your class:
map is not a good name, it may get conflict with std::map if using namespace std; or using std::map was specified somewhere.
The constant array sizes make this class non-reusable. Class should be flexible to allow any N*M sized 2D array. For this, better to use vector<vector<int>>.
getcell should be a const method, and it should do error checking with row and column numbers passed.
If you want this class to have static-sized array sizes and compile time, you may use class templates with row and column sizes as non type template arguments.
template<size_t row, size_t column>
class Level
{
int _map[row][column];
public:
Level(int src[row][column])
{
memcpy(_map, src, sizeof(_map)); // why not simply 'memcpy' ?
}
};
int main()
{
int source[10][2] = { {1, 2}, {3,4} };
Level<10, 2> ten_by_2(source);
}
Here the map is a constant value, which could not been assigned as an lvalue. This could be fixed by iterating the element of the array, and assign a[i][j] to map[i][j].
class Level {
private:
int map[20][30];
public:
Level(int a[20][30]) {
for(int i = 0; i < 20; ++i)
for(int j = 0; j < 30; ++j)
map[i][j] = a[i][j];
}
int getcell(int row, int column) {
return map[row][column];
}
};
I have small question about std::vector. In main.h i try to make fixed size int vector
std::vector<int> foo(7);
But g++ gived this error:
../test/main.h:21:26: error: expected identifier before numeric constant
std::vector<int> foo(7);
../main/main.h:21:26: error: expected ',' or '...' before numeric constant
How can i create private vector variable of fixed size length? Or should i simply make in constructor
for(int i=0; i<7;i++){
foo.push_back(0);
}
Assuming foo is a data member, your syntax is invalid. In general, you can initialize a data member of type T like this:
T foo{ctor_args};
or this
T foo = T(ctor_args);
However, std::vector<int> has a constructor that takes an std::initializer_list<int>, which means that the first form would yield a size-1 vector with a single element of value 7. So you are stuck with the second form:
std::vector<int> foo = std::vector<int>(7);
If you are stuck with a pre-C++11 compiler, you would need to use a constructor:
class bar
{
public:
bar() : foo(7) {}
private:
std::vector<int> foo;
};
and take care to initialize the vector in all constructors (if applicable.)
The most efficient way to initialize a class member (other than built-in type), is to use the initialisation list.
So the best solution here, is to construct your vector of length 7 in the initilization list of your class constructor:
(I also recommend you to use a define for your fixed value 7. If you change it to 8 in the futur your will not have to change the value 7 on all your code)
file.h:
#define YOURCLASSFOOSIZE 7
class yourClass
{
public:
yourClass(): foo(YOURCLASSFOOSIZE) {}
private:
std::vector<int> foo;
};
file.cpp :
for(int i=0; i < YOURCLASSFOOSIZE; i++)
{
foo.push_back(0);
}
I have an array inside a class which is:
private:
static const int MAX_EQUIPS=100;
equip a_t[MAX_EQUIPS];
int a_n;
Then in the main they tell me what MAX_EQUIPS size should be, how can I put it so it changes? It starts at X but then it increases or decreases when the new valor is entered.
It seems you are referring to variable length arrays which are not permitted in C++. many possible alternatives exist, for instance you can use a vector
A c++ solution would be:
class MyClass
{
public:
MyClass( size_t n ) :
a_t( n )
{
}
private:
std::vector< int > a_t;
};
I would suggest using std::vector for this, as it will wrap most of this itself.
private:
std::vector<int> a_t;
Then when you're given the size:
a_t.resize(MAX_EQUIPS);
Your a_n will be a_t.size().
However, if you Really want to do it yourself, you'll need to do some allocation (which you should tie to ctor/dtor semantics.
I am trying to compile this code:
class OthelloState {
public: // constructor
Othello(int r, int c);
/* other stuff */
private: // private data
const int rows;
const int columns;
int board[rows][columns];
}
I keep ending up with:
OthelloState.h:109: error: invalid use of non-static data member 'OthelloState::rows'
OthelloState.h:115: error: from this location
OthelloState.h:115: error: array bound is not an integer constant
OthelloState.h:112: error: invalid use of non-static data member 'OthelloState::columns'
OthelloState.h:115: error: from this location
OthelloState.h:115: error: array bound is not an integer constant
I assume that this means I have to make rows and columns static. But if I make them static, I cannot initialize either with from a constructor, the way I have to for this project...
Is there some other way I can do this?
PS: I know that in real Othello, the board is a square 8 by 8 grid...But after considering how long it would take the computer to generate the next best move on a partial 8 by 8 grid, we are not going to play with "real" Othello board (i.e. no predefined board sizes).
In C++, variable length arrays are not allowed. board[][] needs to know both of its dimensions at compile time. You can use vector<vector<int> > board;, if you want to initialize row and col at runtime.
class OthelloState {
public:
OthelloState(int r, int c);
private: // private data
const int rows; // should be 'unsigned int'
const int columns;
vector<vector<int> > board;
};
Other solution:
Suppose you know rows and cols at compile time then you can use template. That is as good as initializing row and col in constructor.
template<unsigned int row, unsigned int col>
class OthelloState {
public:
...
private:
int board[row][col];
};
Usage:
OthelloState<8,8> obj;
OthelloState<10,10> obj;
if it's always 8x8, then constants are a minimal solution. here's one way to declare it:
class OthelloState {
// ...
private:
enum { rows = 8, columns = 8 };
int board[rows][columns];
};
But after considering how long it would take the computer to generate
the next best move on a partial 8 by 8 grid, we are not going to play
with "real" Othello board (i.e. no predefined board sizes).
I deduce from that sentence that you're working on a homework assignment. If that's the case, then it might not be possible/practical for you to use Boost.MultiArray (unless your instructor advised you that it's okay to use Boost).
That leaves vector< vector<int> > which are a PITA to initialize properly. Before you can even use vector< vector<int> >, you have to loop through each inner vector and resize it.
Boost.MultiArray is basically just an overglorified wrapper around a 1D array of data. I therefore propose a third alternative: Roll up your own 2D wrapper around a flat one-dimensional vector. You can overload operator() to mimic the [][] behavior of 2D arrays:
int operator()(size_t row, size_t col) {/*compute index into 1D array*/}
I posted an example of this kind of wrapper here.
You're trying to dynamically define the size of a compile-time, fixed size array at runtime. You will need to dynamically allocate the memory. You also need your constructor to have the same name as your class
class OthelloState {
public: // constructor
OthelloState(int r, int c)
{
board = new int[r];
for(int i = 0; i < r; i++)
{
board[i] = new int[c];
}
}
/* other stuff */
private: // private data
const int rows;
const int columns;
int **board;
};
Make sure you have matching deletes for all your news in a destructor if you use this method, though