How to design this data structure?
Aug 16, 2014 at 1:20pm UTC
Very often, I believe you will get into this problem.
You design a class like this:
1 2 3 4 5 6 7 8 9 10
class cell_c{
private :
double p;
public :
class_c() {
p=0;
}
inline double p() {return p;}
double Flux() {//this function will use p value of surrounding cell_c};
};
so when you use it, you will declare it first:
vector<cell_c> U;
and you use it like this:
1 2 3
for (int i=0; i!=U.size(); ++i) {
//use U[i].Flux() function here
}
but the problem is: You usually put the class definition in a head file, and the declaration and using of it in another file. But the function
U[i].Flux()
need use
U[i+1].p()
or
U[i-1].p()
, but actually this vector didn't exist yet when you define the cell_c class.
So how would guys fix this, and keep the convenience and privacy? How would you design the data structure? Thanks.
Last edited on Aug 16, 2014 at 1:20pm UTC
Aug 16, 2014 at 2:01pm UTC
Can anyone help solve this problem? Urgent, Waiting online! Thanks!
Last edited on Aug 16, 2014 at 2:24pm UTC
Aug 16, 2014 at 2:58pm UTC
Something like this,perhaps:
1 2 3 4 5 6 7 8 9 10
class cell_c {
// ....
//this function will use p value of surrounding cell_c
// double Flux()
double Flux( const cell_c* left_neighbour = nullptr , const cell_c* right_neighbour = nullptr ) ;
// ....
};
Aug 16, 2014 at 3:14pm UTC
Thanks a lot, JLBorges!
Last edited on Aug 16, 2014 at 3:24pm UTC
Aug 16, 2014 at 3:28pm UTC
> Can I do like this:
The problem with that approach is that vector iterators can be invalidated when the vector is resized.
Perhaps, store the cell's position in the vector instead. Something like this:
cell.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#ifndef CELL_H_INCLUDED
#define CELL_H_INCLUDED
#include <vector>
struct cell
{
inline double value() const { return v ; }
double flux() const ;
static std::vector<cell> objects ;
static cell& create( double v = 0 ) ;
private :
double v = 0 ;
std::vector<cell>::size_type pos = 0 ;
cell( double v, std::vector<cell>::size_type p = 0 ) : v(v), pos(p) {}
};
#endif // CELL_H_INCLUDED
cell.cc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include "cell.h"
std::vector<cell> cell::objects ;
cell& cell::create( double v )
{
objects.push_back( { v, objects.size() } ) ;
return objects.back() ;
}
double cell::flux() const
{
double prev = pos > 0 ? objects[pos-1].value() : 0 ;
double next = pos < ( objects.size() - 1 ) ? objects[pos+1].value() : 0 ;
double result = 0 ;
// compute result using next, prev
return result ;
}
Or, if random access is not a requirement, use
std::list<>
instead of a vector.
Iterators to elements in a list are not invalidated till the element itself is removed.
Last edited on Aug 16, 2014 at 3:28pm UTC
Aug 16, 2014 at 6:44pm UTC
Thanks, JLBorges! But how to use this class definition?
1 2 3 4 5 6 7 8 9
#include "cell.h"
vector<cell> U;
vector<cell> V;
int main() {
//do calculation on U and V
//U[i].objects[j] looks complicated to me
}
and U have a vector member, objects, it is a vector of cells, but each member has a objects member, so repeating like this, no ending?
I got confused!
Aug 16, 2014 at 7:34pm UTC
Perhaps something like this:
cell.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#ifndef CELL_H_INCLUDED
#define CELL_H_INCLUDED
#include <vector>
struct cell
{
inline cell( double v = 0 ) : v(v) {}
inline double value() const { return v ; }
double flux( const std::vector<cell>& container, std::vector<cell>::size_type pos ) const ;
private : double v ;
};
#endif // CELL_H_INCLUDED
cell.cc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include "cell.h"
#include <memory>
#include <limits>
double cell::flux( const std::vector<cell>& container, std::vector<cell>::size_type pos ) const
{
if ( ( pos >= container.size() ) || ( std::addressof( container[pos] ) != this ) )
{
// *** error: invalid position. throw something?
return std::numeric_limits<double >::quiet_NaN() ;
}
double prev = pos > 0 ? container[pos-1].value() : 0 ;
double next = pos < ( container.size() - 1 ) ? container[pos+1].value() : 0 ;
double result = 0 ;
// compute result using next, prev
return result ;
}
And then:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream>
#include "cell.h"
int main()
{
std::vector<cell> first = { {1.6}, {6.7}, {2.3}, {7.8}, {9.9} } ;
for ( std::vector<cell>::size_type i = 0 ; i < first.size() ; ++i )
std::cout << first[i].flux( first, i ) ;
std::vector<cell> second = { {1}, {6}, {3}, {9}, {2}, {7}, {4} } ;
for ( std::vector<cell>::size_type i = 0 ; i < second.size() ; ++i )
std::cout << second[i].flux( second, i ) ;
}
Aug 17, 2014 at 4:42am UTC
if Flux() uses other cells in the collection then it should be a member of the collection, not a member of an individual cell:
1 2 3 4 5
class Cells {
public :
vector<cell> theCells;
Flux(int index); // compute Flux for theCells[index]
};
Topic archived. No new replies allowed.