简体   繁体   中英

modifying an object's std::vector from within another class

Intro:

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.

The 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.

point.cpp:

#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;}

point.h:

#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

polygon.cpp:

#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();
    }
}

polygon.h:

#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

group.cpp:

#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();
        }
    }
}

group.h:

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM