The old const pointer problem
May 15, 2010 at 3:31am UTC
I am writing a Polygon class. The idea is that it should be immutable: ie, you specify the vertices at construction, and then it cannot be modified. I need to be able to iterate over both vertices and edges, and so to prevent redundantly storing the vertices I used a vector of pointers to vertices that make up the edges. Here is my code:
Polygon.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#pragma once
#include "Vector2D.h"
#include <vector>
#include <utility>
using namespace std;
class Polygon {
private :
vector<Vector2D> _vertices;
vector<pair<Vector2D*, Vector2D*> > _edges;
public :
Polygon(const vector<Vector2D>& vertices);
vector<Vector2D>::const_iterator vertexBegin() const ;
vector<Vector2D>::const_iterator vertexEnd() const ;
vector<pair<Vector2D*, Vector2D*> >::const_iterator edgeBegin() const ;
vector<pair<Vector2D*, Vector2D*> >::const_iterator edgeEnd() const ;
};
Polygon.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include "Polygon.h"
#include "assert.h"
Polygon::Polygon(const vector<Vector2D>& vertices) :
_vertices(vertices) {
//A polygon must have at least 3 vertices
assert(vertices.size() > 2);
//Build the edges vector
Vector2D* prev = &(*_vertices.begin());
for (vector<Vector2D>::iterator iter = _vertices.begin() + 1; iter != _vertices.end(); ++iter) {
_edges.push_back(pair<Vector2D*, Vector2D*>(prev, &(*iter)));
prev = &(*iter);
}
}
vector<Vector2D>::const_iterator Polygon::vertexBegin() const {
return _vertices.begin();
}
vector<Vector2D>::const_iterator Polygon::vertexEnd() const {
return _vertices.end();
}
vector<pair<Vector2D*, Vector2D*> >::const_iterator Polygon::edgeBegin() const {
return _edges.begin();
}
vector<pair<Vector2D*, Vector2D*> >::const_iterator Polygon::edgeEnd() const {
return _edges.end();
}
The problem I am having is that using the edge iterator I can now edit the vertices in my polygon. For example, I can do the following:
1 2 3 4 5 6 7 8
vector<Vector2D> points;
points.push_back(Vector2D(12,12));
points.push_back(Vector2D(13,13));
points.push_back(Vector2D(14,14));
Polygon poly(points);
vector<pair<Vector2D*, Vector2D*> >::const_iterator iter = poly.edgeBegin();
(*iter).first->setX(5);
Ideally, I would like the return type of my edge iterator to be something like
const vector<const pair<const Vector2D* const , const Vector2D* const > >
but it seems really difficult or at least inefficient to achieve this conversion.
Can someone suggest how this conversion can be achieved, or perhaps an alternative method of making my Polygon immutable and still providing access to the edges and vertices? I will also be thankful for any general advice on refactoring this code.
May 15, 2010 at 4:11am UTC
Why not implement your own iterator that does just that when dereferenced?
For example,
1 2 3 4
std::pair<const Vector2D *,const Vector2D *> VectorIterator::deref(){ //I can't remember the syntax for the dereference operator
std::pair<Vector2D *,Vector2D *> &element=this ->polygon._edges[this ->position];
return std::pair<const Vector2D *,const Vector2D *>(element.first,element.second);
}
Topic archived. No new replies allowed.