Declaring a static const member of a class.

L

Luca Cerone

Dear all,

I'm having a few difficulties in declaring a class with a static constant member.
This member is a vector of double that has to be created once during
the execution and shared among all the objects.
After being created it can't be modified during the whole execution of my program.

I write a toy example to show you what I'd like to do (it doesn't work,
but I can't figure out a way to code it well, that's why I'm posting here).

#include<iostream>
#include<vector>

class QuadFun{
public:
QuadFun(double a, double b) ; // a and b will be used to initialize
// the private vector y to evaluate the values (x-a)*(x-b)
// x has to be a vector that is shared among all the object of the class.
private:
static const std::vector<double> x; // this will be a vector of uniformly
//spaced numbers from 0 to 1. The number of points is determined
//by reading a configuration file. in this example I set the
//number manually in the main function.
std::vector<double> y;
}

int main() {
int numPoints=50; // this value is actually read from a configuration file
// here is the problem. I don't want the number of points to be a member
// of the class.
QuadFun f1=QuadFun(0,1);
QuadFun f2=QuadFun(0.5,0.75);

// how can I make the vector x mad of numpoints created when I first create
// an object of class QuadFun?
// how can I make it "dynamic" so that if I change the value of numPoints
// the x vector will be created accordingly? (in an other execution).
return 0 ;
}

Hope I could explain well what I'd like to achieve.
I know this code is WRONG, but I can't understand how to write it
in a good way.

Can you help me?
Thanks a lot in advance,
Cheers, Luca
 
S

Saeed Amrollahi

Dear all,

I'm having a few difficulties in declaring a class with a static constantmember.
This member is a vector of double that has to be created once during
the execution and shared among all the objects.
After being created it can't be modified during the whole execution of myprogram.

I write a toy example to show you what I'd like to do (it doesn't work,
but I can't figure out a way to code it well, that's why I'm posting here).

#include<iostream>
#include<vector>

class QuadFun{
  public:
    QuadFun(double a, double b) ; // a and b will be used to initialize
    // the private vector y to evaluate the values (x-a)*(x-b)
    // x has to be a vector that is shared among all the object of the class.
  private:
    static const std::vector<double> x; // this will be a vector of uniformly
           //spaced numbers from 0 to 1. The number of pointsis determined
           //by reading a configuration file. in this exampleI set the
           //number manually in the main function.
    std::vector<double> y;

}

int main() {
  int numPoints=50; // this value is actually read from a configuration file
  // here is the problem. I don't want the number of points to be a member
  // of the class.
  QuadFun f1=QuadFun(0,1);
  QuadFun f2=QuadFun(0.5,0.75);

  // how can I make the vector x mad of numpoints created when I first create
  // an object of class QuadFun?
  // how can I make it "dynamic" so that if I change the value of numPoints
  // the x vector will be created accordingly? (in an other execution).
  return 0 ;

}

Hope I could explain well what I'd like to achieve.
I know this code is WRONG, but I can't understand how to write it
in a good way.

Can you help me?
Thanks a lot in advance,
Cheers, Luca

Hello
My pretty quick solution:
// quad_fun.h
#include<vector>

class QuadFun{
public:
QuadFunc(double a, double b);
const std::vector<double> GetY() const { return y; }
static bool filled; // to make sure, we filled x already
private:
static std::vector<double> x;
static void FillX(); // static member function for filling X
std::vector<double> y;
};

// quad_fun.cpp
#include "quad_fun.h"
using std::vector;
vector<double> QuadFun::x;
bool QuadFun::filled = false;
extern int numPoints;

QuadFun::QuadFun(double a, double b)
{
FillX();
y.clear();
for (vector<double>::size_type i = 0; i < x.size(); ++i)
y.push_back((x - a) * (x - b));
}

void QuadFun::FillX()
{
if (!filled)
for (int i = 0; i < numPoints; ++i)
x.push_back(i % 3 + 0.0); // fill with 0 or 1, just an example
filled = true;
}

// quad_fun_main.cpp
#include "quad_fun.h"
#include <iostream>
#include <algorithm>
#include <iterator>

int numPoints; // this value is actually read from a configuration
file
int main() {
using namespace std;

cout << "Number of points ";
cin >> numPoints;
QuadFun f1= QuadFun(0,1);
vector<double> y = f1.GetY();
copy(y.begin(), y.end(), ostream_iterator<double>(cout, "\t"));
cout << '\n';
QuadFun f2=QuadFun(0.5,0.75);
y = f2.GetY();
copy(y.begin(), y.end(), ostream_iterator<double>(cout, "\t"));
return 0 ;
}

HTH,
-- Saeed Amrollahi Boyouki
 
L

Luca Cerone

Hi Ed, thanks a lot for your reply!
1. The C++ concept of const does not strictly allow for run-time
initialization such as you desire; and
2. Initialization in the constructor (which might be different for each
instance) is inconsistent with the static definition (which is shared by
all instances).
3. A static const requires a definition with an initial value.

Ok probably I got everything wrong.
I thought that you used const to avoid overwriting a value that has already been defined; and I thought that static (for class members) is used to share
the same location of memory among all the objects.

So the idea of declaring something as static const correspond to "initialize
the member once, share it among all the objects and forbid modifications".

As this is wrong, what is "static const" actually used for?
The third problem is essentially a syntax error. The usual solution for
the second problem would be to add a static member function to
initialize the vector. And here is a reasonably good solution to the
first problem:

In the function you use to initialize the vector, use const_cast to
obtain a non-const pointer to the vector.

I'm sorry I'm not aware of the const_cast type... what is it?
You can then initialize it as
you require. If it is inconvenient to guarantee that the initialization
function is called only once, you might instead declare the static
member as a pointer to vector, declared with value NULL. If the
initialization function sees NULL, it instantiates the vector,
initializes it as desired, and then sets the pointer (using const_cast).

ok I think I got it..
so in my class I need a static pointer to a vector x, initially set to null that is assigned by the constructor (if it is not null).
But how can I avoid writing on x again?

This is a fairly standard work-around when it is necessary to bend the
concept of const to something similar to (but different from) the C++
concept.

/Ed

I actually don't understand something though.
It seems pretty reasonable to me that a class object my depend on certain
parameters input by the user somehow (keyboard, reading a file etc. etc.).

Isn't there a way to "parameterize" a class, so that its members will depend
on certain parameters?

Thanks again for your answer.
I'm sorry if I ask silly question, I'm a 3weeks "experienced" c++ programmer,
and after 10 years of Matlab programming I feel like I've never programmed before :)

Cheers,
Luca
 
L

Luca Cerone

Thanks a lot to all of you.
I've received many inputs and I hope I'll be able to make
things work soon.

Creating the a public accessor, and a private member to set the
value seems a good idea.

Thanks a lot for the explanations,
the examples and the different solutions proposed!

Cheers, Luca
 
P

Pavel

Luca said:
Thanks a lot to all of you.
I've received many inputs and I hope I'll be able to make
things work soon.

Creating the a public accessor, and a private member to set the
value seems a good idea.

Thanks a lot for the explanations,
the examples and the different solutions proposed!

Cheers, Luca
Meyer's singleton may fit your description better (to create x when you first
create QuadFun -- that is, not to initialize it at all if you do not create
them). For example:


class QuadFun{
public:
QuadFun(double a, double b) ; // a and b will be used to initialize
// the private vector y to evaluate the values (x-a)*(x-b)
// x has to be a vector that is shared among all the object of the class.
private:
static const std::vector<double> &GetX() {
static std::auto_ptr<const std::vector<double> >
x(InitializeXFromConfigFile());
return *x;
}
static std::vector<double> * InitializeXFromConfigFile(); // not shown
// this will be a vector of uniformly
//spaced numbers from 0 to 1. The number of points is determined
//by reading a configuration file. in this example I set the
//number manually in the main function.
std::vector<double> y;
}

QuadFun::QuadFun(double a, double b): y() {
const std::vector<double> &x = GetX();
unsigned n = x.size();
y.reserve(n);
for (unsigned i = 0; i < n; ++i)
y = (x - a) * (x - b);
}

Disclaimers: I did not try to complile the above and Meyer's singletons "in
pure" are not "thread-safe".

HTH
-Pavel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top