Как изменить вектор из базового класса через функцию производного класса - PullRequest
1 голос
/ 25 февраля 2020

Я создал базовый класс Shape_2D, который наследуется всеми классами фигур

Shape_2D.h

private:
    std::vector<Point> points_within_shape_;
    std::vector<Point> points_on_perimeter_;

public:
    std::vector<Point> get_Points_Within_Shape();
    std::vector<Point> get_Points_On_Perimeter();

Для Shape_2D класса Shape_2D есть только 1 конструктор. cpp

Shape_2D::Shape_2D(const std::string &name, const bool &contain_Warp_Space)
    : name_(name), contain_warp_space_(contain_Warp_Space) {}

std::vector<Point> Shape_2D::get_Points_Within_Shape()
{
    return this->points_within_shape_;
}

std::vector<Point> Shape_2D::get_Points_On_Perimeter()
{
    return this->points_on_perimeter_;
}

Учитывая приведенный выше код, я хочу получить все точки внутри фигуры (в данном случае прямоугольник) и вернуть ей вектор для всех точек.

функция для этого реализуется индивидуально для каждой фигуры. Этот пример - класс прямоугольника ниже.

Прямоугольник. cpp

Rectangle::Rectangle(const std::array<Point, 4> &vertices, const bool &warp_space)
    : Shape_2D("Rectangle", warp_space), vertices_(vertices), area_(compute_Area())
{
    get_Points_Within_Shape() = get_All_Point_In_Shape();
    get_Points_On_Perimeter() = get_All_Point_On_Shape();
}

std::vector<Point> Rectangle::get_All_Point_In_Shape()
{
    std::vector<Point> points_within_shape;
    for (int x = vertices_[0].get_X() + 1; x < vertices_[2].get_X(); x++)
    {
        for (int y = vertices_[1].get_Y() + 1; y < vertices_[0].get_Y(); y++)
        {
            if (is_Point_In_Shape(x, y))
                points_within_shape.push_back(Point(x, y));
        }
    }
    return points_within_shape;
}

std::vector<Point> Rectangle::get_All_Point_On_Shape()
{
    std::vector<Point> points_on_perimeter;
    for (int x = vertices_[0].get_X(); x <= vertices_[2].get_X(); x++)
    {
        for (int y = vertices_[1].get_Y(); y <= vertices_[0].get_Y(); y++)
        {
            if (is_Point_On_Shape(x, y))
                points_on_perimeter.push_back(Point(x, y));
        }
    }
    return points_on_perimeter;
}

Однако, когда я запускаю их через отладчик, я обнаруживаю, что, несмотря на то, что функция работает правильно, вектор, объявленный в Shape_2D, не будет обновляться соответственно. Что я могу сделать, чтобы это исправить?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

Ваша проблема в том, что вы определили функции get_Points_Within_Shape() и get_Points_On_Perimeter() как возвращающие копии внутренних векторов. Вместо этого вы должны определить их, чтобы они возвращали ссылки на внутренние векторы. Также обычно есть 2 версии для таких функций: обычная функция, возвращающая обычный вектор, и const функция, возвращающая const вектор. Т.е. ваша декларация должна выглядеть примерно так:

std::vector<Point>& get_Points_Within_Shape() {return points_within_shape_;}
const std::vector<Point>& get_Points_Within_Shape() const {return points_within_shape_;}
0 голосов
/ 25 февраля 2020

Проблема в том, что методы get_Points_Within_Shape и get_Points_On_Perimeter возвращают копию вектора точек, поэтому вы просто присваиваете эту копию, которая затем уничтожается после завершения выполнения оператора (поскольку он не был сохранен в переменная).

Здесь вы можете сделать points_within_shape_ и points_on_perimeter_ защищенными, чтобы производный класс мог получить к ним доступ (как предлагается в комментариях), или обеспечить перегрузку для функции-получателя. это позволяет изменять данные:

std::vector<Point> &get_Points_Within_Shape()
{
    return points_within_shape_;
}    
const std::vector<Point> &get_Points_Within_Shape() const
{
    return points_within_shape_;
}

Обратите внимание, что первый метод предоставляет возможность доступа к данным, поскольку он возвращает неконстантную ссылку. Другой альтернативой может быть реализация установщика в базовом классе:

void set_Points_Within_Shape(const std::vector<Point> &points)
{
    points_within_shape_ = points;
}

Даже если вы решите использовать установщик, вам все равно следует изменить класс получателя так, чтобы он возвращал const std::vector<Point> &. Таким образом, вы не будете копировать все точки в новый вектор каждый раз, когда хотите их прочитать. Если в векторе много точек, это может привести к значительному снижению производительности.

PS Хотя это самый простой способ, избегайте объявления производного класса friend. Это следует использовать только в некоторых определенных c случаях, и определенно не в случае, когда один класс наследуется от другого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...