2

So for one of my assignments i have to generate random graphic circles and rectangles, using structures. but i cannot fathom how to get the structure to output from a functions.

   struct Circle{
   int x;
     int y;
     int radius;
     int r;
     int g;
     int b;
   };

   Circle createCirc() {
     int x = rand() % window_Width;
     int y = rand() % window_Height;
     int radius = rand() % 100;
     int r = rand()%256;
     int g = rand()%256;
     int b = rand()%256;
     return Circle(x,y,radius,r,g,b);
   }

here i create the struct with basic values for the object, then i pass some data from main into this function.

 Circle circle[1000];
 circle[count] = createCirc();

however i cannot even get it to run as apparently when defining the struct itself it comes with this error:

main.cpp:47:8: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 6 were provided

I just do not understand how to pass the data from the function into the varable in main.

2
  • 8
    Rather than making createCirc a function that returns a Circle, why not make it a constructor? Commented Nov 6, 2018 at 19:17
  • how do i do that instead of a function? im not the best at this Commented Nov 6, 2018 at 19:37

4 Answers 4

10

You can use

 return Circle(x,y,radius,r,g,b);

only when there is an explicitly defined constructor that takes those arguments. Change it to:

 return {x,y,radius,r,g,b};

The second form uses aggregate initialization to construct a Circle.

Sign up to request clarification or add additional context in comments.

Comments

1

Just create a new Circle inside your createCirc() function and return it:

Circle createCirc() {
    Circle circle;
    circle.x = rand() % window_Width;
    circle.y = rand() % window_Height;
    circle.radius = rand() % 100;
    circle.r = rand()%256;
    circle.g = rand()%256;
    circle.b = rand()%256;
    return circle;
}

Also you should think about using a vector for dynamic allocation and storage.

4 Comments

wouldnt that dismiss the point of trying to have multiple circles if its returning itself?
its not returning itself, the function createCirc() is just initializing a new Circle-Object and returning it - this has nothing to do with your struct and default values of it.
Better to turn createCirc into a constructor.
This constructs a temporary Circle and makes a copy for the caller to copy into the array they're actually going to use. The larger the object gets, the more important this is
1
struct Circle {
    int x;
    int y;
    int radius;
    int r;
    int g;
    int b;
};

You are only defining fields to the class, but not a constructor.

The () initialization syntax does not allow to do what you're doing.
However, C++11 aggregate-initialization can, as pointed out by @RSahu 's post.

An alternative is to define a constructor to your class, optionally using the member-initialization list (see a few reasons here why to).

Essentially, it would do what your createCirc function is attempting to do. You would define it as such:

struct Circle {
    int x, y, radius, r, g, b;

    Circle();
};

Circle::Circle() :
    x{rand() % window_width},
    y{rand() % window_height},
    radius{rand() % 100},
    r{rand() % 256},
    g{rand() % 256},
    b{rand() % 256}
{}

This would allow you to do something like Circle myCircle; and it will get initialized as you expect.

That being said, a constructor is not necessarily the best way to do this (IMO it hides too much behavior here) but it's a good thing to know.

3 Comments

Actually, I'm not sure - is return {a, b, c}; aggregate initialization or something different entirely? I know that it's not the same as return SomeClass{a, b, c};.
It is. "using the member-initialization list" Why not show that as an example and explain why it is usually prefered to assignment in the ctors body?
@Swordfish Thanks, I've modified my example to use the member initialization list. I feel like that it's not terribly relevant in this particular case (it's pure data) so I linked to another SO post which gives more general information about it. I was not sure how to sum it up so I rather didn't.
0

The following should work nicely.

struct Circle
{
    Circle(); // the default constructor
    int x;
    int y;
    int radius;
    int r;
    int g;
    int b;
};

Circle::Circle() : // start member-initialization list
   x( rand() % window_Width ),
   y( rand() % window_Height ),
   radius( rand() % 100 ),
   r( rand()%256 ),
   g( rand()%256 ),
   b( rand()%256 )
{
    // nothing to do!
}

I choose this implementation for a couple of reasons. The main reason is that you want to construct 1000 of these and store them in an array. When an array of objects is created (assuming it isn't an array of int or other plain data type) the default constructor will be called for each element. That's what we defined here. And by using the member-initialization list we get those initial values into the member variables more efficiently than we would by assigning them in the body of the constructor. That isn't terribly important for int values, but it's a good habit to get into.

Note that if you wanted to construct Circles with other values, it would be a waste of time to use this default constructor. You'd want to define another constructor that takes parameters for size, position, and/or RGB values.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.