push_back(нов триъгълник)

В C++ от FLTK, за да дефинираме кръг, използваме код като този:

Circle c(Point(x,y), r);

И можем да използваме vector_ref да ги поставим и запазим във вектор, като:

Vector_ref<Circle> vc;
vc.push_back(new Circle(Point(x,y),r));

Добре, това бяха за Circle и досега нямаше проблем! Триъгълникът може да бъде дефиниран така за използване в кодове:

Graph_lib::polygon poly;
poly.add(Point(x1,y1),r1);
poly.add(Point(x2,y2),r2);
poly.add(Point(x3,y3),r3);

и това е вектор за запазването им:

Vector_ref<Graph_lib::Polygon> vp;

Проблемът е, че как да запишете/поставите triangles/polygons в този vp вектор, като използвате ключова дума new, както прави кръгът?

Кодът, който използвах като отговор на упражнение № 12 (от тук) е това:

/* The binary-tree class, one of the topics that has been said in Programming Principles and Practice using C++ book by Biarne Stroustrup.
   This code is written by R Abbasi ([email protected]) */
#include <Simple_window.h>
#include <iostream>

vector <Graph_lib::Polygon> vpo;
vector <Point> vp;
int pow(int);

class Binary_tree: public Shape {
public:
    Binary_tree(Point _p, int l):level(l), p(_p) {  
        preparing(); }

    void preparing();
    void put_nodes(Point);
    void wheel(Point);
    void make_nodes(Point);
    void draw_lines() const {
        for(int i = 0; i*2+2 < vp.size(); i++) {
            fl_line(vp[i].x,vp[i].y,  vp[i*2+1].x,vp[i*2+1].y);
            fl_line(vp[i].x,vp[i].y,  vp[i*2+2].x,vp[i*2+2].y);
        }
    }

private:
    Point p;
    int i, j, k, level;
    double scale;
};
//**********************************

void Binary_tree::preparing() {
    if(level < 1) error("Bad inputted level!");
    else if (level == 1) put_nodes(p);
    else {
        scale = 5 * pow(level); 
        i = 1; j = 1; k = 3; 
        put_nodes(p); 
        make_nodes(p);
    }
}

//***************************************

void Binary_tree::put_nodes(Point p) { 
    vp.push_back(p);
    Graph_lib::Polygon poly;
    poly.add(Point(p.x-2,p.y));
    poly.add(Point(p.x,p.y-3));
    poly.add(Point(p.x+3,p.y));

    vpo.push_back(&poly);
}

//******************************************

void Binary_tree::wheel(Point p) {
    put_nodes(Point(p.x - scale, p.y+30));
    put_nodes(Point(p.x + scale, p.y+30));
}

//*****************************************

void Binary_tree::make_nodes(Point p) {
    while(vp.size() < (pow(k)-1))
        wheel(vp[vp.size()-i++]);

    if(i < pow(level)) {
        k++;
        scale *= 1.0/2.0;
        make_nodes(vp[vp.size()-i]);
    }
}

//*********************

int pow(int l)  {
    int m = 2; 
    for(int k = 2; k < l; k++) m *= 2; 
    return m;
}

//***************************************

int main() try
{
    Simple_window win(Point(),1300,500, "Binary_tree");
    int level;
    cout<< "Please enter the level of the Binary-tree:";
    if(!(cin>>level)) error("Bad number of level!");

    Point p(10*pow(level),20);
    Binary_tree b_t(p,level);

    vpo[0].set_color(Color::red);
    vpo[0].set_style(Line_style(Line_style::solid,3));
        win.attach(vpo[0]);
    for(int i=1; i<vpo.size(); i++) {
        vpo[i].set_color(Color::blue);
        win.attach(vpo[i]);
    }
    win.attach(b_t);
    win.wait_for_button();
    return 0;
}

//*****************************

catch(exception& e) {
    cerr << e.what() << "\n\a";
    return 0;
}

А грешките са:

*Грешка 9 грешка C2664: 'void std::vector‹_Ty>::push_back(Graph_lib::Polygon &&)': не може да конвертира параметър 1 от 'Graph_lib::Polygon *' в 'Graph_lib::Polygon &&' c:\ потребители\cs\documents\visual studio 2012\projects\test_1\test_1\test_1.cpp 53

14 IntelliSense: няма екземпляр на претоварена функция "std::vector‹_Ty, _Alloc>::push_back [с _Ty=Graph_lib::Polygon, _Alloc=std::allocator]" съответства на списъка с аргументи Типовете аргументи са: (Graph_lib:: Многоъгълник ) тип обект е: std::vector> c:\Users\CS\Documents\Visual Studio 2012\Projects\test_1\test_1\test_1.cpp 53


person Aria    schedule 11.10.2014    source източник
comment
Наистина ли трябва да използвате new? Ако го направите, трябва да кажете защо. И обяснете как работи натискането на Circle указател във вектор от Circles.   -  person juanchopanza    schedule 11.10.2014
comment
Предполагам, че трябва да начертаете своето класово наследство.   -  person Maxim Gotovchits    schedule 11.10.2014
comment
не разбрах   -  person Aria    schedule 11.10.2014
comment
Ще получите синтактична грешка, ако използвате new. Просто използвайте vc.push_back(Circle(Point(x,y),r)) - Погледнете вашия поли пример - не използвате new там.   -  person cup    schedule 11.10.2014
comment
C++ прави разликата между указатели, препратки, локални обекти и временни обекти. Трябва да използвате правилната форма. Когато функция очаква динамично разпределен обект (т.е. указател), използвайте ключовата дума new. В противен случай трябва да подадете временен обект без ключовата дума new и функцията ще направи копие на този обект. Това описание е опростено - трябва да имате уводна книга за C++ през първите 6 месеца от изучаването на C++.   -  person rwong    schedule 11.10.2014
comment
@cup: Използването на vc.push_back(new Circle(Point(x,y),r)); (в горния код) не прави никаква грешка, докато vc.push_back(Circle (Точка(x,y),r)); създава грешка Debug Assertion failed. Така че трябва да използвам нов. Както и да е, проблемът ми не е кръг, а многоъгълник. Имам нужда от начин да вкарам полигони във вектора или vector_ref.   -  person Aria    schedule 11.10.2014
comment
@rwong: Чета тази книга и упражнението, свързано с моя проблем, не е номер 12 от това.   -  person Aria    schedule 11.10.2014


Отговори (1)


За Vector_ref<polygon> (с помощта на new)

Доколкото разбирам за Vector_ref, това е просто std::vector с указатели и код за почистване на динамично разпределената памет в края. Това означава, че трябва да използвате new, за да разпределите своя полигон. Така че, ако трябва да използвате new, можете първо да създадете своя многоъгълник (използвайки new) и след това да го натиснете:

// Create your new polygon
polygon* poly = new polygon;
poly->add(Point(...));
poly->add(...);
poly->add(...);

// Push that polygon into the vector
vp.push_back(poly);

За std::vector<polygon*> (вземане на адреса)

Ако многоъгълникът не излезе извън обхвата (т.е. не излезете от функцията или не подадете }), можете да вземете адреса на многоъгълника:

// Create polygon
polygon poly;
poly.add(...); // by 3

// Add the polygon to the vector
vp.push_back(&poly);

За std::vector<polygon> (правя копие)

Ако векторът не е масив от указатели, какъвто е случаят за std::vector<polygon> (но не и за std::vector<polygon*> или Vector_ref<polygon>), тогава не трябва да използвате new или &. Вместо това, ако просто използвате push_back от вектора с многоъгълника, многоъгълникът ще бъде копиран във вектора.

// Create your new polygon
polygon poly;
poly.add(...); // by 3

// Copy the polygon into the vector
vp.push_back(poly);
person ilent2    schedule 11.10.2014
comment
Благодаря за отговора. Това е просто и правилно. Но тъй като не съм научил указатели до тази част от книгата (предложих връзката й по-горе), не мога да използвам указатели и трябва да реша проблема по някакъв друг начин :( - person Aria; 11.10.2014
comment
Всеки път, когато използвате ключовата дума new, вие използвате указател. В този случай съм присвоил указателя към променлива (обозначена с *). Единствената друга разлика е достъпът до членове на указатели, вместо . можете да използвате ->. - person ilent2; 11.10.2014
comment
@user3724662 Добавих алтернатива, това все още използва указател, но го скрива (най-вече). Вашият оригинален пример с кръг също използва указател, тъй като използва ключовата дума new. - person ilent2; 11.10.2014
comment
Използвах втория метод и добавих целия код в тялото на въпроса. Има грешки. Моля, погледнете въпроса още веднъж. - person Aria; 11.10.2014
comment
@user3724662 А, разбирам. Предположих, че използвате Vector_ref за вашите полигони, а не std::vector. Доколкото мога да разбера, Vector_ref е масив от указатели с някакъв почистващ код. За вашия случай трябва да можете просто да използвате push_back без фантастични екстри. Ако това не работи, публикувайте новия изход на компилатора. Късмет. - person ilent2; 12.10.2014
comment
Вместо vector_ref многоъгълници, което би усложнило много, използвах vector_ref от Lines, което също е нещо като Shape и е точно като Circle (за поставяне в vector_ref). Триъгълникът е направен от 3 линии, така че с помощта на Lines мога да реша проблема. Благодаря :) - person Aria; 12.10.2014