Can you create a Vector of structs in C++? I need help with a unknown error pertaining to this subject.

Started by
21 comments, last by uglybdavis 11 years, 4 months ago
I am painting 64 squares onto a screen using Fast Light ToolKit. In order to save time I created a loop to do this automatically. Since I need to dynamically create new objects I decided to push the struct Rectangle into a vector. However when I run the program I get a single error.
error C2248: 'Graph_lib::Shape::Shape' : cannot access private member declared in class 'Graph_lib::Shape'


Here is the main loop

int main()
{
Point tl(100,100); //top left corner of window
Simple_window win(tl,400,400,"My Window");
vector<Rectanglee> rects; //Here is where I think the problem lies.

for (int i=0;i<8;i++){
int xa=(i*50)-1;
for(int j=0;j<8;j++){
int ya=(j*50)-1;
Rectanglee rect(Point(i,j),50,50);
rects.push_back(rect);
}
}
for(int i=0;i<64;i++){
win.attach(rects); //attach rect to screen
}
win.wait_for_button(); //wait until user clicks the next button to close window
}




Here is the rectanglee struct.

struct Rectanglee : Shape {
Rectanglee(Point xy, int ww, int hh) : w(ww), h(hh)
{
add(xy);
if (h<=0 || w<=0) error("Bad rectangle: non-positive side");
}
Rectanglee(Point x, Point y) : w(y.x-x.x), h(y.y-x.y)
{
add(x);
if (h<=0 || w<=0) error("Bad rectangle: non-positive width or height");
}
void draw_lines() const;
int height() const { return h; }
int width() const { return w; }
private:
int h; // height
int w; // width
};
Advertisement
That error says that the [font=courier new,courier,monospace]Shape[/font] constructor is private. Can you post the code for [font=courier new,courier,monospace]Shape[/font]?

That error says that the [font=courier new,courier,monospace]Shape[/font] constructor is private. Can you post the code for [font=courier new,courier,monospace]Shape[/font]?


Yes.

Here are the headers I am using http://www.stroustrup.com/Programming/Graphics/ . The shape is in the graph.h file I think.


Anyways here is the Shape class.

class Shape { // deals with color and style, and holds sequence of lines
public:
void draw() const; // deal with color and draw lines
virtual void move(int dx, int dy); // move the shape +=dx and +=dy
void set_color(Color col) { lcolor = col; }
Color color() const { return lcolor; }
void set_style(Line_style sty) { ls = sty; }
Line_style style() const { return ls; }
void set_fill_color(Color col) { fcolor = col; }
Color fill_color() const { return fcolor; }
Point point(int i) const { return points; } // read only access to points
int number_of_points() const { return int(points.size()); }
virtual ~Shape() { }
protected:
Shape();
virtual void draw_lines() const; // draw the appropriate lines
void add(Point p); // add p to points
void set_point(int i,Point p); // points=p;
private:
vector<Point> points; // not used by all shapes
Color lcolor; // color for lines and characters
Line_style ls;
Color fcolor; // fill color
Shape(const Shape&); // prevent copying
Shape& operator=(const Shape&);
};
Shape isn't copyable, so any derived classes are also not copyable and you can only stick copyable objects in a vector. You could try a vector of (smart) pointers instead.
It looks like whoever wrote Shape didn't want them to be copied, but you are making a vector of Rentanglees, which implies copying them around, and the copy constructor for Rectanglee tries to invoke the copy constructor for Shape.

EDIT: Ninja'd.
Okay. Thanks for the help. biggrin.png
May i suggest (read the comments, i changed them:

[source lang="cpp"]int main() {
Point tl(100,100);
Simple_window win(tl,400,400,"My Window");
vector<Rectanglee*> rects; // Pointer Magic!

for (int i=0;i<8;i++){
int xa=(i*50)-1;
for(int j=0;j<8;j++){
int ya=(j*50)-1;
rects.push_back(new Point(i,j),50,50);
}
}
for(int i=0;i<64;i++){
win.attach(*(rects)); //Remember to de-reference
}
win.wait_for_button(); //wait until user clicks the next button to close window

// Clean up at some point!
for (unsigned int i = 0, size = rects.size(); i < size; ++i)
delete rects;
}[/source]

May i suggest (read the comments, i changed them:
*snip*


FYI, putting raw pointers into a container like [font=courier new,courier,monospace]vector[/font] like that is a fantastic way to introduce memory leaks, double deletes, etc. Best use a smart pointer.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
vector <int*> names; works, so then wouldn't you have a vector of structs or classes if the int* referred to the addresses in memory of different data structs?
Airlight is looking for game developers

vector <int*> names; works, so then wouldn't you have a vector of structs or classes if the int* referred to the addresses in memory of different data structs?


For the reasons above having raw pointers to Rectanglee in the vector is generally not a good idea unless you have the experience to know what you are really doing (and if the OP is confused by a private copy constructor then he is definitely not there). Dropping all type safetype by forcing a cast from int* to Rectanglee* is much, much worse for absolutely no benefit. You lose all type safety and gain exactly nothing over the Rectanglee* implementation. You also have the option of walking well off into undefined behavior if you do not understand the casts between the involved pointers very well and depending on how your inheritance hierarchy looks. And you still have to allocate storage for the Rectanglee somewhere somehow for the pointers to point to.

Even setting those things aside, why would you store int* instead of Rectanglee*? If something like that has to be done (and I cannot imagine any reason out of the top of my head that is not done better by other methods), why not use at least void*?

That said, the obvious candidate to solve the issues is boost::shared_ptr. In C++11 either std::shared_ptr or std::unique_ptr would do the job. Of course if we had C++11 I would rather make the involved type movable and just stick them into containers normally (if possible).

This topic is closed to new replies.

Advertisement