Как мне передать функцию, содержащую вектор с разными типами данных, с этими разными типами данных?

#c #pointers #vector

#c #указатели #вектор

Вопрос:

Я все еще пытаюсь понять, что я хочу сделать. Мой код должен принимать определенные пользователем сегменты (например, линию, круг или любое другое определение геометрического сегмента, которое я буду реализовывать) и объединять их в вектор. Однако порядок типов сегментов («линия», «круг», …) определяется пользователем и, следовательно, может варьироваться от выполнения к выполнению.

Прежде чем я продолжу: каждый сегмент имеет разные входные данные, необходимые для его собственного создания (например, линия не имеет радиуса, только начальная и конечная точки).

Мой предпочтительный подход был бы

  1. прочитайте пользовательский ввод и определите порядок сегментов
  2. создайте каждый сегмент
  3. Передайте их функции (например, функции-члену / методу для класса, реализующего контур).
  4. Эта функция создает контур, например, путем реализации вектора.

Мой текущий тестовый код имеет жестко запрограммированную последовательность сегментов, но трюк, которого я хочу добиться, заключается в том, что порядок (и количество) сегментов не жестко запрограммированы. К сожалению, я не могу понять, как.

Вот код:

 #include <iostream>
#include <vector>

struct point
{
    double x;
    double y;
};

class segment
{
public:
    segment() 
    {
        P1.x = 0;
        P1.y = 0;

        P2.x = 0;
        P2.y = 0;
    };
    virtual ~segment() {};

    virtual double get_radius() { return 0; };
    virtual double get_length() { return 0; };
    virtual double get_angle() { return 0; };

    int segment_id = 0;

protected:
    point P1;
    point P2;
};

class Line : public segment
{
public:
    Line() {};
    Line(const point pt1, const point pt2)
    {
        P1.x = pt1.x;
        P1.y = pt1.y;

        P2.x = pt2.x;
        P2.y = pt2.y;

        segment_id = 1;
    };

    ~Line() {};

    double get_length() { return calc_length(); };
    double get_angle() { return calc_angle(); };

private:
    double calc_length()
    {
        // calculate length (here: dummy value)
        return 1;
    }

    double calc_angle()
    {
        // calculate angle (here: dummy value)
        return 0.5;
    }

    double length = 0;
    double angle = 0;
}
;

class circle : public segment
{
public:
    circle()
    {
        center.x = 0;
        center.y = 0;
    };
    circle(const double r, const point c)
    {
        radius = r;
        center.x = c.x;
        center.y = c.y;

        segment_id = 2;
    };

    ~circle() {};

    double get_radius() { return radius; };
    point get_center() { return center; };
    double get_length() { return 3.14 * radius; }; //returns circumference

private:
    double radius = 0;
    point center;
};

//-------------------------------------------------------

int main()
{
    int nbr = 5;
    point start;
    start.x = 1;
    start.y = 2;

    point end;
    end.x = 3;
    end.y = 4;

    point c;
    c.x = 0;
    c.y = 0;

    double r = 9;

    auto anotherCircle = std::make_unique<circle>(r, c);
    auto anotherLine = std::make_unique<Line>(start, end);

    std::unique_ptr<circle> yet_anotherCircle;

    circle* myCircle = new circle(r, c);
    Line* myLine = new Line(start, end);
    
    //VERSION 1: Does not compile. I get an exception in <memory> line 1762 when trying to delete _Ptr
    //std::vector<std::unique_ptr<segment>> v1;
    //v1.emplace_back(anotherCircle);
    //v1.emplace_back(anotherLine);
    //std::cout << v1[0]->get_radius() << std::endl;
    //v1.emplace_back(myLine);
    //std::cout << v1[1]->segment_id << std::endl;

    //VERSION 2: Compiles
    std::vector<std::unique_ptr<segment>> v2;

    v2.emplace_back(std::make_unique<circle>(r, c));

    v2.emplace_back(std::make_unique<Line>(start, end));

}
 

Прямой способ, который я себе представляю, но который, похоже, не работает, потребует работы версии 1. Тогда я мог бы, вероятно, использовать объекты шаблона, которые я передаю в вектор. К сожалению, это не тот путь, и я не имею ни малейшего представления, как к этому подойти. Было бы здорово, если бы кто-нибудь мог мне здесь помочь! Спасибо!

Ответ №1:

Вам нужно перемещать элементы в векторе, так как ваши элементы не могут быть скопированы:

 v1.emplace_back(std::move(anotherCircle));
 

Комментарии:

1. Вау! ЭТО РАБОТАЕТ! Спасибо! Я два дня бился над этим вопросом, и вы решили его для меня менее чем за пять минут. К сожалению, я могу проголосовать только один раз.