I have a struct Point, which has a constructor with parameters and a class called Circle.
struct Point{
int x, y;
Point(){}
Point(int ox, int oy) : x(ox),y(oy){}
};
class Circle{
public:
Point obj;
int radius;
Circle(Point pt(int ox, int oy), int raza) : obj.x(ox), obj.y(oy), radius(raza) {}
};
int main()
{
Circle(Point p(2,3),3);
return 0;
}
The problem is that I don't know how to pass a struct constructor with parameters as parameter to my Circle class constructor.
You can do that like this :
class Point
{
public:
Point(int x, int y) :
m_x(x),
m_y(y)
{
}
private:
int m_x{ 0 };
int m_y{ 0 };
};
class Circle
{
public:
Circle(const Point& pt, int raza) :
m_point{ pt },
m_radius{ raza }
{
}
private:
Point m_point;
int m_radius;
};
int main()
{
Circle c1(Point(2,3), 3);
// or use this shorter variant.
// first parameter is a Point, {2,3} looks for a constructor
// of Point with two ints of point and finds it.
Circle c2({ 2,3 }, 3);
return 0;
}
Circle(Point pt(int ox, int oy), int raza) : obj.x(ox), obj.y(oy), radius(raza) {}
is wrong syntax and should simply be:
Circle(Point pt, int raza) : obj(pt), radius(raza) {}
And then
Circle circle(Point(2, 3), 3);
What you intended could be done in the following ways
Circle(int ox, int oy, int raza) :
obj(ox, oy)
radius(raza)
{}
Or
Circle(Point const& pt, int raza) :
obj(pt), //note, here is the implicitly defined copy-constructor of obj called, not the one you defined
radius(raza)
{}
So If you define either of the constructors above the following will be valid
Circle crl(1,2,3); //valid for the first constructor
Circle crl(Point(1,2),3); //valid for the second constructor
Circle crl({1, 2}, 3); //valid for the second constructor
Related
I have class Point, and i'm coding Circle. Then how to pass class as variable
int main() {
Point p1(0, 0), p2(5, 8);
Circle c1(p1, 4), c2(p2, 3);
int sgd = c1.getIntersection(c2);
cout<<"intersection: "<<sgd<<endl;
}
this is class Ponit
class Point {
private:
int _x;
int _y;
public:
Point() {
_x = 0;
_y = 0;
}
Point(int x, int y) {
_x = x;
_y = y;
return Point(_x, _y);
}
};
at this point the problem is located in the class circle,
you need to modify it so it can take a point as parameter:
class Circle
...public:
Circle(const Point& P, int s);
after that you can pass objects/instances of the class point
like
Circle c1(p1, 4), c2(p2, 3);
this approach will require that the Circle class "knows" about a Point class, this is called dependencies since the Circle depends on the Point...
you can as work-around, define a Circle constructor with the 2 params too
Circle(int x, int y, int s);
I found solution for it:
class Point {
public:
int _x;
int _y;
}
and in class Circle
Circle(Point x, int s);
I made a struct as a data member in class. Now, I want to make a constructor to which I will pass my data members. How can I pass struct in constructor.
I wrote this code but it's not working.
#include <iostream>
#include <cmath>
using namespace std;
class circle
{
private:
struct center
{
int xcord;
int ycord;
};
struct center cordinate;
float radius;
public:
circle()
{
cordinate.xcord=0;
cordinate.ycord=0;
radius=0;
};
circle(int x, int y, float r) : cordinate.xcord(x), cordinate.ycord(y), radius(r)
{};
void showdata()
{
cout<<"Center(x,y) = ("<<cordinate.xcord<<","<<cordinate.ycord<<")"<<endl;
cout<<"Radius = "<<radius<<endl;
}
};
int main()
{
circle c1;
c1.showdata();
}
Or if I wrote it like this, it still don't work.
circle(int x, int y, float r) : center.xcord(x), center.ycord(y), radius(r)
{};
or
circle(int x, int y, float r) : center.cordinate.xcord(x), center.cordinate.ycord(y), radius(r)
{};
How can I pass struct to constructor?
You can initialize the cordinate member like this:
circle(int x, int y, float r) : cordinate{x, y}, radius{r} {}
Also, your default constructor can be simplified to:
circle() : circle(0, 0, 0) {}
which delegates to the 3-argument constructor. Even better, just use in class member initializers for all the fields:
struct center
{
int xcord = 0;
int ycord = 0;
} cordinate;
float radius = 0;
and then you can default the default constructor:
circle() = default;
Here's a demo.
Can anybody help me with the syntax of passing an array of classes
to another class. The syntax of passing an array of classes to another
class has got me beaten. class line tries to be initialised by an
array of points, but the prototype does not match.
#include <iostream>
using namespace std;
class point {
public:
point() {}
point(int x, int y) : X(x), Y(y) {}
void setXY(int x, int y) { X = x; Y = y; }
int getX() { return X; }
int getY() { return Y; }
private:
int X, Y;
};
class line {
public:
line(point *points, int); // Problem line.
private:
point *coords;
int numpoints;
};
int main() {
point points[3];
points[0].setXY(3, 5);
points[1].setXY(7, 9);
points[2].setXY(1, 6);
line l(points, 3); // Problem line.
return 0;
}
Error message:
cygdrive/c/Tmp/cc4mAXRG.o:a.cpp:(.text+0xa7): undefined reference to `line::line(point*, int)'
You need to define a constructor for your line class - you've only provided a declaration.
#include <iostream>
using namespace std;
class point {
public:
point() {}
point(int x, int y) : X(x), Y(y) {}
void setXY(int x, int y) { X = x; Y = y; }
int getX() { return X; }
int getY() { return Y; }
private:
int X, Y;
};
class line {
public:
line(point *points, int count)
: coords(points), numpoints(count) {}
private:
point *coords;
int numpoints;
};
int main() {
point points[3];
points[0].setXY(3, 5);
points[1].setXY(7, 9);
points[2].setXY(1, 6);
line l(points, 3);
return 0;
}
I'd recommend taking a look at the difference between definitions and declarations. Additionally, you should consider maintaining a std::vector<point> in your line class to manage the points. Your line class might then behave as:
#include <vector>
class line {
public:
line(std::vector<point> points)
: coords(points), numpoints(coords.size()) {}
private:
std::vector<point> coords;
int numpoints;
};
You didn't provide a definition for the constructor.
Try:
line(point *points, int np) : coords(points), numpoints(np) {}
Missing body of constructor "line".
You define prototype only.
How to use a single constructor only to create the following objects using C++:
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
class A should be having a single constructor to accomodate the creation of objects x, y and z. No change is allowed in the 3 lines specified above.
You cannot(rather should not!) have a single constructor to create all these objects.
You can have constructors which can take different parameters precisely for this reason.
The important question to be asked is:
What exactly are you trying to achieve? What is the need for this?
Perhaps you are trying to solve a problem in wrong way. If you can provide some detail We could help you better.
Yuck!!!!
Anyway, if I was forced to (for example if this, hypothetically speaking, were a homework problem) I would use some sort of variant:
class Variant {
public:
Variant();
Variant( int );
Variant( double );
Variant( const char * );
~Variant();
private:
union data { ... };
enum type { ... };
};
And then use that in my horrid single constructor, along with default arguments to allow empty construction.
A::A( Variant p1 = Variant(), Variant p2 = Variant(), Variant p3 = Variant() );
With c++11:
#include <iostream>
struct A
{
template<typename... Args> A(Args&&... x)
{
std::cout << "construct A\n";
}
};
int main()
{
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
return 0;
}
In C++03 you can use initialization funntion:
class A
{
public:
A(int x, const char* y, double z)
{
Init(x, y, z);
}
A(const char* y, int x)
{
Init(x, y);
}
A()
{
Init();
}
private:
void Init(int x = 0, const char* y = 0, double z = 0)
{
}
};
In C++11 you can use constructor delegation:
class A
{
public:
A(int x, const char* y, double z)
{
}
A(const char* y, int x)
: A(x, y, 0)
{
}
A()
: A(0, 0, 0)
{
}
};
Why not just:?
class A {
public:
A(...) { }
};
// test:
int main() {
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
}
I use the named constructor idiom to create objects, because I have lots of calls with identical parameters but the object shall be created differently.
The C++ FAQ tell us how to do this. It also tells us how to force objects being heap allocated. Yet it really fails to tell us how to use the named constructor idiom with the new operator.
Because new requires a constructor to be called we cannot directly call named constructors. So I found two workarounds to this problem:
I create an additional copy constructor and hope that optimizing compilers won't create a temporary object.
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
point_t(const point_t &x) : X(x.X), Y(x.Y) { }
static point_t carthesian(int x, int y) { return point_t(x,y); }
static point_t polar(float radius, float angle) {
return point_t(radius*std::cos(angle), radius*std::sin(angle));
}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
/* XXX: hope that compiler doesn't create a temporary */
point_t *x = new point_t(point_t::carthesian(1,2));
x->add(1,2);
}
The other version is to create separate named constructors. Because function overloading doesn't work on return type I use two different names, which is ugly.
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
/* XXX: function overloading doesn't work on return types */
static point_t carthesian(int x, int y) { return point_t(x,y); }
static point_t *carthesian_heap(int x, int y) { return new point_t(x,y); }
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = point_t::carthesian_heap(1,2);
x->add(1,2);
}
Is there a prettier version that is equal to the example code?
You can avoid named constructor idiom for this completely, and do it using an additonal dummy enum parameter to select the constructor.
enum Carthesian {carthesian};
enum Polar {polar};
class point_t {
int X,Y;
public:
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
point_t(Carthesian, int x, int y) :X(x),Y(y){}
point_t(Polar, float radius, float angle)
: X (radius*std::cos(angle)), Y(radius*std::sin(angle)) {}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = new point_t(carthesian,1,2);
point_t *y = new point_t(polar,0,3);
x->add(1,2);
}
It is simple, portable, and the only overhead you will see is for the passing of the dummy enum values. In the rare case this overhead is too high for you it can be eliminated by wrapping a function call even when the construction itself is not inlined, as follows:
enum Carthesian {carthesian};
enum Polar {polar};
class point_t {
int X,Y;
void initCarthesian(int x, int y); // may be long, not inlined
void initPolar(float radius, float angle);
public:
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
point_t(Carthesian, int x, int y)
{initCarthesian(x,y);} // this is short and inlined
point_t(Polar, float radius, float angle) {initPolar(radius, angle);}
void add(int x, int y) { X += x; Y += y; }
};
Another approach is to use a derived class for construction. When using inner classes, it leads into quite a nice syntax I think:
class point_t {
int X,Y;
public:
struct carthesian;
struct polar;
point_t(int x, int y) : X(x), Y(y) { } // may keep as a default
void add(int x, int y) { X += x; Y += y; }
};
struct point_t::carthesian: public point_t
{
carthesian(int x, int y):point_t(x,y){}
};
struct point_t::polar: public point_t
{
polar(float radius, float angle):point_t(radius*std::cos(angle),radius*std::sin(angle)){}
};
int main(int argc, char **argv) {
point_t *x = new point_t::carthesian(1,2);
point_t *y = new point_t::polar(0,3);
x->add(1,2);
return 0;
}
You could write :
point_t *x = new point_t(point_t::carthesian(1,2));
It first calls carthesian() and then the copy-constructor.
Or, is there any problem in it? Perhaps, a bit slow?
By the way, there is one clear advantage in this code: the programmer can clearly see the new operator in his code (where he is using point_t written by someone else), so you can assume that its his responsibility to call delete once he is done with x.
Is this really a problem? In my experience classes tend to be either dynamically allocated most of the time or seldom, if at all. Classes that represent values, such as your point_t class here, belong to the second category, while classes that represent entities (i.e. something with identity) belong to the first one.
So my suggestion is to chose what you think is the best approach for each class and only provide that. Note that you could always return a small directly allocated object which has a private pointer to a larger one, as in the Handle-Body idiom.
On the other hand, other answers show how you may disambiguate among constructors that take arguments of the same number and types. In this line of thought, one alternative approach is to introduce specific types for the arguments as follows:
class radius_t {
float R;
public:
explicit radius_t(float r) : R(r) {}
operator float() const { return R; }
};
class angle_t {
float A;
public:
explicit angle_t(float a) : A(a) {}
operator float() const { return A; }
};
class point_t {
float X,Y;
public:
point_t(float x, float y) : X(x), Y(y) { }
point_t(radius_t radius, angle_t angle) :
X(radius*std::cos(angle)), Y((radius*std::sin(angle)) {
}
void add(int x, int y) { X += x; Y += y; }
};
int main(int argc, char **argv) {
point_t *x = new point_t(radius_t(1),angle_t(2));
x->add(1,2);
}
One approach that I haven't seen is overloading the constructor making the heap allocation use the last argument as an out one (Granted that the second function is not technically a constructor, it doesn't return an instance). The result would be something like (taken as base your second code fragment):
class point_t {
int X,Y;
point_t(int x, int y) : X(x), Y(y) { }
public:
/* XXX: function overloading doesn't work on return types */
static point_t carthesian(const int x, const int y) { return point_t(x,y); }
static void carthesian(const int x, const int y, point_t * & point) { point = new point_t(x,y); }
void add(int x, int y) { X += x; Y += y; }
void add(const point_t & point) { this->X += point.x; this->Y += point.y; }
};
int main(int argc, char **argv) {
point_t p1 = point_t::carthesion(1, 2);
point_t * p2;
point_t::carthesian(1, 2, p2);
p2->add(p1);
}
Can think of template allocator:
template<typename T>
struct Allocator : T
{
template<typename A1, typename A2>
Allocator(A1 a1, A2 a2) : T(a1, a2) {}
};
class point_t {
//...
template<typename T> friend struct Allocator;
};
int main(int argc, char **argv) {
point_t *x = new Allocator<point_t>(1,2);
x->add(1,2);
}
Now Allocator is friend of point_t. So it can access its private constructor. Also, you can add few more constructors like <A1, A2> inside Allocator to make it more generalized. Advantages are:
It doesn't look verbose.
You don't have to worry about compiler optimizations
The friendship is not exploited as, Allocator is a template
and we use it solely for heap allocation
Demo.