italy
Offline
Full Member
Karma: 2
Posts: 207
Muuuuu
|
 |
« on: May 04, 2012, 07:14:14 am » |
Hello, I want to initialize a long vector of a constant N_ELEMENTS elements in a constructor. I know the size of the vector only when initializing the object of that class. Do you know how can I declare it? I have tried in this way: private: const int N_ELEMENTS; unsigned long myVector[N_ELEMENTS] public: myClass(int N_ELEMENTS=20):myVector[N_ELEMENTS]; //the constructor
but the complier say "invalid use of non-static data member"
|
|
|
|
|
Logged
|
|
|
|
|
North Queensland, Australia
Offline
Edison Member
Karma: 31
Posts: 1179
|
 |
« Reply #1 on: May 04, 2012, 07:21:54 am » |
The error is for the line unsigned long myVector[N_ELEMENTS] as N_ELEMENTS must be initialised during the constructor, the size cannot be known at compile time, late binding impedes this approach. What you need is early binding. template< const int i_Elements > class myClass{
private:
unsigned long myVector[ i_Elements ]; };
Instantiate an object like myClass< 4 > m_Class1;
//rather than myClass m_Class1( 4 );
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 89
Posts: 9393
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #2 on: May 04, 2012, 07:42:24 am » |
or use dynamic memory ... malloc() ?
|
|
|
|
|
Logged
|
|
|
|
|
italy
Offline
Full Member
Karma: 2
Posts: 207
Muuuuu
|
 |
« Reply #3 on: May 04, 2012, 07:57:17 am » |
thanks pYro_65! do you also hknow how to declare the template in constructor in the cpp file? I have declared the class in this way "template< const int i_Elements > class myClass" in the header. In the cpp declarations like this one: "template< const int i_Elements> myClass::myClass()" seems not to be accepted.
|
|
|
|
|
Logged
|
|
|
|
|
italy
Offline
Full Member
Karma: 2
Posts: 207
Muuuuu
|
 |
« Reply #4 on: May 04, 2012, 07:59:44 am » |
@robtillaart Yes malloc is a solution but I prefer to avoid pointers in C++ because they increase the probability of errors. I prefer to work more with class and object. Anyway you're right
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #5 on: May 04, 2012, 05:09:35 pm » |
This compiles: template< const int i_Elements > class myClass { private: const int n_Elements; unsigned long myVector [i_Elements]; public: myClass () : n_Elements (i_Elements) {}; };
void setup () { myClass<4> foo; Serial.begin (115200); Serial.println (sizeof foo, DEC); }
void loop () {} Output: 18
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #6 on: May 04, 2012, 05:11:23 pm » |
However you can't replace the 4 by a variable, as the template doesn't know what code to generate. Then you need dynamic memory allocation, or use the STL.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #7 on: May 04, 2012, 06:41:12 pm » |
Yes malloc is a solution but I prefer to avoid pointers in C++ because they increase the probability of errors. No. The use of pointers does not increase the probability of errors. The misuse of pointers, on the other hand, does. Learning to properly use pointers is not a waste of time and effort.
|
|
|
|
|
Logged
|
|
|
|
|
Online
Edison Member
Karma: 15
Posts: 1005
Arduino rocks
|
 |
« Reply #8 on: May 04, 2012, 06:58:46 pm » |
Yes malloc is a solution but I prefer to avoid pointers in C++ because they increase the probability of errors. No. The use of pointers does not increase the probability of errors. The misuse of pointers, on the other hand, does. Learning to properly use pointers is not a waste of time and effort. For every line you must type, there is a change you will mistype it or forget to do it. Thus, since you must declare the pointer, allocate memory from it, and free the memory (I guess that's technically optional on a uC) as opposed to just defining the object, you have the opportunity to make more errors with pointers. I also consider it better design to use templates rather than malloc when possible.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35483
Seattle, WA USA
|
 |
« Reply #9 on: May 04, 2012, 07:12:19 pm » |
For every line you must type, there is a change you will mistype it or forget to do it. Thus, since you must declare the pointer, allocate memory from it, and free the memory Oh, I know. I just hate when I have to think and code at the same time. (I guess that's technically optional on a uC) Uh, no, freeing memory is not optional on a uC. as opposed to just defining the object, you have the opportunity to make more errors with pointers. Better to let someone else do the thinking, eh?
|
|
|
|
|
Logged
|
|
|
|
|
Online
Edison Member
Karma: 15
Posts: 1005
Arduino rocks
|
 |
« Reply #10 on: May 04, 2012, 07:20:00 pm » |
For every line you must type, there is a change you will mistype it or forget to do it. Thus, since you must declare the pointer, allocate memory from it, and free the memory Oh, I know. I just hate when I have to think and code at the same time. as opposed to just defining the object, you have the opportunity to make more errors with pointers. Better to let someone else do the thinking, eh? I'm not saying it's hard, just it increases the probability of errors. People seem to have figured this out, since they invented smartptr and similar constructs so one doesn't need to worry about it. (I guess that's technically optional on a uC) Uh, no, freeing memory is not optional on a uC. For a global object, you want it to last until the memory is forcefully cleared by a reset. This thread is about allocating and forgetting about it. Obviously you need to free memory if you're going to be repeatedly allocating it.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA
Offline
God Member
Karma: 4
Posts: 673
|
 |
« Reply #11 on: May 04, 2012, 10:00:35 pm » |
I will definitely vote for dynamic allocation. Seems a lot cleaner than templates for ints. (Although I will apologize in advance if this needs tweaks to compile on the stock Arduino avr-gcc... I should keep a copy of old compilers just to make sure my forum posts still compile  ) After the constructor is finished, you never have to think about myVector as a pointer. Just treat it like an array, except don't use sizeof() on it. class myClass { private: int N_ELEMENTS; unsigned long *myVector; public: myClass(int N_ELEMENTS=20) { myVector = new unsigned long[N_ELEMENTS]; } ~myClass() { delete[] myVector; } };
|
|
|
|
|
Logged
|
|
|
|
|
North Queensland, Australia
Offline
Edison Member
Karma: 31
Posts: 1179
|
 |
« Reply #12 on: May 04, 2012, 10:07:00 pm » |
Dynamic memory doesn't win in this situation. template< const int i_Elements > class myClass { private: unsigned long myVector [ i_Elements ]; public: myClass(){}; };
To start off with, No SRAM is used storing the count of elements as the object is explicitly bound to i_Elements value. No new and delete operators are required. No destructor is required due to automatic variable destruction. Almost exactly the same, just doing it in 0 lines of code.
|
|
|
|
|
Logged
|
|
|
|
|
italy
Offline
Full Member
Karma: 2
Posts: 207
Muuuuu
|
 |
« Reply #13 on: May 07, 2012, 04:53:02 am » |
thanks
|
|
|
|
|
Logged
|
|
|
|
|
|