In my program, a group
object has an std::vector
full of polygons (a ring and holes) and a polygon
object has an std::vector
of points. In reality, the classes are more complicated, I've stripped them down here to illustrate my problem.
I want to be able to modify the point
'sx and y coordinates from within it's corresponding group object. Below, in group.cpp
, I have a dummy function called void Group::tryChangingAllX()
that tries to accomplish this. However, calling show()
on the group afterwards shows no change to it's polygon's point's coordinates.
I think I need to use references/pointers, but I need a nudge in the right direction.
#include "point.h"
#include <iostream>
Point::~Point(){}
Point::Point(int x, int y){
_x = x;
_y = y;
}
void Point::show(){std::cout << "(" << x() << "," << y() << ")";}
void Point::x(int x){_x = x;}
void Point::y(int y){_y = y;}
int Point::x(){return _x;}
int Point::y(){return _y;}
#ifndef POINT_GUARD
#define POINT_GUARD
class Point{
int _x;
int _y;
public:
Point(int x, int y);
~Point();
void show();
int x();
int y();
void x(int x);
void y(int y);
};
#endif
#include "polygon.h"
#include "point.h"
#include <iostream>
#include <vector>
Polygon::~Polygon(){}
Polygon::Polygon(){}
std::vector<Point> Polygon::points(){return _points;}
Polygon::Polygon(std::vector<Point> points){_points = points;}
void Polygon::show(){
std::cout << "Points: ";
for(std::vector<Point>::size_type i = 0; i != _points.size(); i++) {
_points[i].show();
}
}
#ifndef POLYGON_GUARD
#define POLYGON_GUARD
#include <vector>
#include "point.h"
class Polygon{
//private:
std::vector<Point> _points;
public:
~Polygon();
Polygon ();
Polygon(std::vector<Point> points);
std::vector<Point> points();
void show();
};
#endif
#include <iostream>
#include <vector>
#include "group.h"
#include "polygon.h"
Group::~Group(){}
Group::Group(std::vector<Polygon> polygons){
_ring = polygons.front();
polygons.erase(polygons.begin());
_holes = polygons;
}
void Group::tryChangingAllX(){
std::vector<Point> points = _ring.points();
for(std::vector<Point>::size_type i = 0; i != points.size(); i++) {
points[i].x(15);
}
}
void Group::show(){
_ring.show();
if(_holes.size()>0){
for(std::vector<Polygon>::size_type i = 0; i != _holes.size(); i++) {
_holes[i].show();
}
}
}
#ifndef GROUP_GUARD
#define GROUP_GUARD
#include <vector>
#include "polygon.h"
class Group{
Polygon _ring;
std::vector<Polygon> _holes;
public:
~Group();
Group(std::vector<Polygon> polygons);
void show();
void tryChangingAllX();
};
#endif
Thanks!
The function
std::vector<Point> points();
returns by value , so when you call it, you get a copy of the member. You need to change it to
std::vector<Point>& points();
After you've done this
std::vector<Point> points = _ring.points();
also makes a copy of the returned value. To refer to the actual member in _ring
, change to:
std::vector<Point>& points = _ring.points();
That should do it.
Note that you should pass std::vector
by const reference to prevent an un-necessary copy:
Polygon(const std::vector<Point>& points);
and consider making methods that don't modify the class const
:
int x() const;
This is exactly your problem - you're getting a copy of your points rather than working on a reference to the original points themselves.
polygon.cpp:
return points by reference not value:
std::vector<Point>& Polygon::points(){return _points;} // note the '&' in the return
group.cpp:
obtain a reference to the points, not a copy
std::vector<Point>& points = _ring.points(); // note the '&' in what you're getting
Answers posted by Luchian and lori are technically correct. But there are design considerations that I want to point out.
Returning a reference
will allow anyone to modify private
parts of Polygon
object. By design you only want Group
class to do this. Consider making Group
a friend
of Polygon
. Group
then will have access to private bits of Polygon
. This will ensure a tighter encapsulation overall.
In polygon.h
friend class Group;
In group.cpp
void Group::tryChangingAllX()
{
for(std::vector<Point>::size_type i = 0; i != _ring._points.size(); i++)
{
_ring._points[i].x(15);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.