How to design this data structure?

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
Can anyone help solve this problem? Urgent, Waiting online! Thanks!
Last edited on
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 ) ;

    // ....

};
Thanks a lot, JLBorges!
Last edited on
> 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
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!
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 ) ;
}
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.