I have
Triangle::Triangle()
{
A = NULL;
B = NULL;
C = NULL;
}
Triangle::Triangle(Point& X,Point& Y, Point& Z)
{
A = new Point;
*A = X;
B = new Point;
*B = Y;
C = new Point;
*C = Z;
}
and
istream& operator>>(istream& in, Triangle& T)
{
Point X,Y,Z;
in>>X>>Y>>Z;
Triangle T(X,Y,Z);
return in;
}
Where Point is another class which defines a point with coordonates X and Y.
I don't know how to call the constructor with multiple arguments in the overloaded function. Can you help me?
This is how you do it:
Point px;
Point py;
Point pz;
Triangle trig(px, py, pz);
trig will be the object, which is an instance of class Triangle and the above would call the constructor with 3 Point arguments.
Another way is for pointers:
Triangle *pTrig = new Triangle(pX, pY, pZ);
In addition, I suggest, that this would be better:
Triangle::Triangle()
: A(NULL), B(NULL), C(NULL)
{
}
Triangle::Triangle(const Point& X,const Point& Y, const Point& Z)
: A(new Point(X)), B(new Point(Y)), C(new Point(Z))
{
}
Assuming that Point has a copy constructor.
You want to call it from inside the operator>> function to update argument T, but this won't work, because you cannot call the constructor on something that's already constructed. Instead, what you need is to implement an assignment operator. Please see http://en.wikipedia.org/wiki/Assignment_operator_%28C%2B%2B%29 for more information.
Then you can do T = Triangle(X,Y,Z);
To implement the assignment operator, you can do this:
Triangle& Triangle::operator= (const Triangle& other)
{
if (this != &other) // protect against invalid self-assignment
{
if (A != NULL) delete A;
if (B != NULL) delete B;
if (C != NULL) delete C;
A = new Point(other.A);
B = new Point(other.B);
C = new Point(other.C);
}
return *this;
}
Assuming Point has copy constructors. To implement copy constructors, please see http://en.wikipedia.org/wiki/Copy_constructor
A copy constructor looks like the following, but you need to do it for Point:
Triangle& Triangle::Triangle(const Triangle& other)
: A(new Point(other.A)), B(new Point(other.B)), C(new Point(other.C))
{
}
}
The first two constructors are overrides for default constructor. The third function is operator overloading which overloads >> operator. You just need to create an object of Triangle class as follow:
Triangle tr(x,y,z);
or
Triangle* tr = new Triangle(x,y,z);
Where x, y, and z are objects of Point class.
By the way, as you can see in your operator overloading (the third function), you are already creating an object of class Triangle (Triangle T(X,Y,Z);).
Related
I want to use the - operator between 3 objects but I can't.
Error:'A A::operator-(A, A)' must take either zero or one argument
I do not know what to do.
class A
{
private:
float x,y;
public:
void set(int a,int b){
x=a;
y=b;
}
void show(){
cout<<"x = "<<x<<" y = "<<y<<endl;
}
A() {}
A operator -(A &obj1){
A temp;
temp.x= x - obj1.x;
temp.y= y - obj1.y;
return temp;
}
};
A A::operator -(A obj1, A obj2);
int main() {
A ob1,ob2,ob,result;
ob1.set(5,7);
ob2.set(10,7);
ob.set(4,9);
result = ob - ob2 -ob1;
ob.show();
return 0;
}
There are 2 ways to overload an operator for a class:
class Foo {
public:
Foo operator -(const Foo &rhs) const { ... }
Foo operator +(const Foo &rhs) const;
};
Foo Foo::operator +(const Foo &rhs) const {
...
}
or
class Foo { ... };
Foo operator -(const Foo &lhs, const Foo &rhs) { ... }
The first is overloading the operator inside the class as a function of the class. It has this as the left hand side of the operator so you can only specify the right hand side as argument.
The second overloads the general operator outside of the class. It has 2 arguments, the left hand side and the right hand side. It is not a member of the class and won't have access to the private parts, unless you friend it.
You kind of mixed the two styles together and that is what the error is trying to tell you.
You do not need to implement anything to make a - b - c work as the compiler will transform that into temp = a - b; temp - c;.
I know this question has already been ask, but I couldn't figure it out.
I have two classes Point and Line, and 2 Points are members of Line. However in the Line constructor I get "no default constructor exists for the class" error. How can I fix this problem?
#include <cstdlib>
#include <cmath>
#include "PointClass.h"
using namespace std;
class Line {
public:
Line(const Point& p1, const Point& p2) {
this->point1 = p1;
this->point2 = p2;
}
Point point1;
Point point2;
static double Distance(Point p1, Point p2, Point p3) {
double distance = (abs((p1.y - p2.y) * p3.x - (p2.x - p1.x) * p3.y + p2.x * p1.y - p2.x * p1.x) / (sqrt(pow((p2.y - p1.y), 2.0) + pow((p2.x - p1.x), 2.0))));
return distance;
}
};
class Point {
public:
Point(double a, double b) {
this->setCoord(a, b);
}
double x;
double y;
void setCoord(double a, double b)
{
this->x = a;
this->y = b;
}
};
The reason for you error, is that this code calls the Point default constructor (which doesn't exist)
Line(const Point& p1, const Point& p2) {
this->point1 = p1;
this->point2 = p2;
}
instead you should write it like this
Line(const Point& p1, const Point& p2) : point1(p1), point2(p2) {
}
Your version calls the Point default constructor and then assigns the point values. My version initialises the points by calling the Point copy constructor
The error message says "no default constructor", so you should add ones.
class Line {
public:
Line() {} // add this
Line(const Point& p1, const Point& p2) {
class Point {
public:
Point() {} // add this
Point(double a, double b) {
or ones with initialization (safer):
class Line {
public:
Line() : point1(), point2() {} // add this
Line(const Point& p1, const Point& p2) {
class Point {
public:
Point() : x(0), y(0) {} // add this
Point(double a, double b) {
or constructors with default arguments:
The core reason you are getting that error. Is because Line constructor doesn't know how to initialize point1 and point2 prior to your assignment statements in the constructor. That's what constructor initialization lists are for. It's usually better to do initial member initialization in the constructor initialization list instead of in the constructor body. Without a constructor initialization list, point1 and point2 get constructed with the default constructor (error because it's missing) and then immediate updated with additional code in constructor body. You can avoid the need for a default constructor on Point by having Line constructor defined as follows:
Line(const Point& p1, const Point& p2) : point1(p1), point2(p2)
{}
That will resolve your compiler error. Further, it's still not a bad idea to have a default constructor for Point. It's the type of class where it's often useful to have such a constructor. And some point later, you might need to have a collection of Point instances and the compiler will complain again without it. MakeCAT's answer is correct in that regards.
Aside: Your Distance function is passing Point parameters by value. This means the compiler needs to construct 3 new instances of Point each time Distance is invoked. Change your function signature for Distance as follows. If this doesn't make the compiler happy, it will at the very least, generate more efficient code.
static double Distance(const Point& p1, const& Point p2, const& Point p3) {
double distance = (abs((p1.y - p2.y) * p3.x - (p2.x - p1.x) * p3.y + p2.x * p1.y - p2.x * p1.x) / (sqrt(pow((p2.y - p1.y), 2.0) + pow((p2.x - p1.x), 2.0))));
return distance;
}
The problem is that you don't have a default constructor for that class and therefore when you create the points you don't know what values their variables will take.
The easiest and fastest way of solutions is to give default values to the constructor when it does not receive parameters
class Point {
public:
//only modification here
Point(double a = 0, double b = 0) {
this->setCoord(a, b);
}
double x;
double y;
void setCoord(double a, double b)
{
this->x = a;
this->y = b;
}
};
The default constructor is the constructor without parameters. If you have a user provided constructor taking parameters (like your Line constructor taking two Points) then you don't automatically get the default constructor, you need to add it yourself.
I suggest changing your classes
to use in-class initializers
to use member initialization instead of setting in the constructor body
defaulting the default constructor (which requires step 1)
You can compare the IsoCppCoreguidelines for a more detailed explanation on these changes.
class Point {
public:
Point() = default;
Point(double a, double b) : x{a}, y{b} {}
double x{};
double y{};
};
class Line {
public:
Line() = default;
Line(const Point& p1, const Point& p2) : point1{p1}, point2{p2} {}
Point point1{};
Point point2{};
};
I am trying to find a simple example program that overloads the following operators of a mathematic vector.
Constructor // create
= (equals) // assign
+; -; +=; -= // add sub
*; /; *=; /= // multi divide
++; -- // plus minus
== // compare
>; >=
<; <=
[] // access a value
Cant seem to find any good simple tutorials. I emphasize the simple because I am only learning this stuff now. If someone could link me or even better program a simple overload for just one of the operators as an example would be incredible!
There are a few things to know when you write operators, which are not as often used with other functions.
The assign operators, for example, will return *this because you change the value of the vector:
class v {
public:
double x_, y_;
v& operator += (const v& rhs)
{
_x += rhs._x;
_y += rhs._y;
return *this;
}
};
Another interesting one, the pre ++ and post ++ are different only because of an unused parameter:
class v {
public:
double x_, y_;
v& operator ++ (); // ++v
v& operator ++ (int); // v++
};
The "equal" (assignment) is another one that is tricky when you use pointers. For a vector, it generally won't be a problem, but if you define a vector V and assign it to itself, you have to be careful:
class v {
public:
double x_, y_;
v& operator = (const v& rhs)
{
if(this != &rhs)
{
x_ = rhs.x_;
y_ = rhs.y_;
}
return *this;
}
};
In your case, the if() will most certainly not be useful, but think about doing something like this:
delete p_;
p_ = new foo;
p_->x_ = rhs.p_->x_;
If &rhs == this, then the delete p_ deleted the rhs pointer! That means accessing it on the 3rd line is a bug.
The rest should be easy enough to work with. The compare operators return bool and are const:
class v {
public:
double x_, y_;
bool operator == (const v& rhs) const
{
return x_ == rhs.x_ && y_ == rhs.y_;
}
};
Although, since C++20, you are expected to only declare the three way comparison operator <=> which allows the compiler to implement all the other comparison operators for you. This one returns a negative number (smaller: a < b), 0 (equal: a == b), or a positive number (larger: a > b).
I'm not sure what makes a vector bigger or smaller, I used the length from (0, 0) in this example:
class v {
public:
double x_, y_;
int operator <=> (const v& rhs) const
{
if(x_ == rhs.x_ && y_ == rhs.y_)
{
return 0;
}
return length() > rhs.length() ? 1 : -1;
}
};
Except for the [] operator. There are two versions of that one:
class v {
public:
// I would imagine you'd use an array but as a simple example...
double x_, y_;
double operator [] (int idx) const
{
return idx == 0 ? x_ : y_;
}
v_ref operator [] (int idx)
{
v_ref v(this, idx);
return v;
}
};
As you can see, the non-constant version of the [] operator returns a reference. This is necessary so you can write something like:
r[3] = 7.3;
r[3] returns that reference, then the assignment of the reference is called with 7.3 as the parameter. (Note that we should probably throw an error if you use 3 as the index when you only have 2 values: 0 and 1--this is not shown here)
class v_ref
{
public:
v *p_;
int i_;
v_ref(v *p, int i)
: p_(p), i_(i)
{
}
operator = (double q)
{
// again, I suppose you'd use an array instead!
if(i_ == 0)
{
p_->x_ = q;
}
else
{
p_->y_ = q;
}
}
};
Assuming you want some security, the vector pointer could make use of a reference counter so you know whether a main vector object gets deleted before all of its reference objects...
Another note: I would imagine that your constructor will allocate an array of double (or use an std::vector<double> type...) If you use new, remember to delete in the destructor and that's when the if() in the assignment operator is very important.
i have three pointers to three objects:
MyClass* a = new MyClass(...);
MyClass* b = new MyClass(...);
MyClass* c = new MyClass(...);
Now i want to specify an operator in MyClass so that I can do:
a = b*c;
So a,b, and c are already existing large objects which i do not want to make any additional copies of. I want to do the multiplication and directly write the result 'a'.
1) Is this even possible with c++ operators?
2) Could someone give me some hints at the syntax? (i'm a bit new to operators..)
Grateful for any help.
If you wrote operator* for MyClass.
MyClass* a = new MyClass(...);
MyClass* b = new MyClass(...);
MyClass* c = new MyClass(...);
you should use it like below:
*a = (*b) * (*c);
And you can not do it for pointers. For example this is impossible:
MyClass *operator*(const MyClass *a, const MyClass *b) // Impossible
{
...
}
Because the operator definition must have an argument of MyClass.
You really don't want to do this. Sticking with the standard way of defining operators for values and not pointers-to-values will make everything a lot cleaner and easier to maintain.
EDIT As aschepler points out in the comments you can't even do this. At least one of the arguments must be of a class type or a reference to a class.
If you want to avoid huge copy operations, you should use C++11 move semantics or emulate them through something like a MoveProxy or the Boost.Move support-library.
Example code:
// loads of memory with deep-copy
struct X {
int* mem;
X() : mem(new int[32]) { }
// deep-copy
X(const X& other)
: mem(new int[32]) { std::copy(other.mem, other.mem+32, this.mem); }
~X() { delete[] mem; }
X& operator=(const X& other) { std::copy(other.mem, other.mem+32, this.mem); return *this; }
X(X&& other) : mem(other.mem) { other.mem = nullptr; }
X& operator=(X&& other) { delete[] mem; this.mem = other.mem; other.mem = nullptr; return this; }
friend void swap(const X& x, const X& y)
{ std::swap(x.mem, y.mem); }
friend
X operator*(const X& x, const X& y)
{ return X(); }
};
class sample
{
private:
int radius;
float x,y;
public:
circle()
{
}
circle(int rr;float xx;float yy)
{
radius=rr;
x=xx;
y=yy;
}
circle operator =(circle& c)
{
cout << endl<<"Assignment operator invoked";
radius=c.radius;
x=c.x;
y=c.y;
return circle(radius,x,y);
}
}
int main()
{
circle c1(10,2.5,2.5);
circle c1,c4;
c4=c2=c1;
}
In the overloaded '=' function the statements
radius=c.radius;
x=c.x;
y=c.y;
itself make all of c2's data members equal to c1's , so why is a return necessary?
Similarly, in c1=c2+c3, c2 and c3 are added using an overloaded + operator and the value is returned to c1, but doesn't that become c1=, so shouldn't we be using another = operator to assign the sum of c2 and c3 to c1? I'm confused.
It's not needed (i.e. a void return type is legal), but standard practice is to return a reference to *this to allow assignment chaining without any efficiency overhead. E.g.:
class circle
{
int radius;
float x, y;
public:
circle()
: radius(), x(), y()
{ }
circle(int rr, float xx, float yy)
: radius(rr), x(xx), y(yy)
{ }
circle& operator =(circle const& c)
{
std::cout << "Copy-assignment operator invoked\n";
radius = c.radius;
x = c.x;
y = c.y;
return *this;
}
};
int main()
{
circle c1(10, 2.5f, 2.5f);
circle c2, c3;
c3 = c2 = c1;
}
Returning a new object by value, as you're doing, is certainly non-standard, as it creates unnecessary temporaries.
It's not mandatory, but returning a reference to *this allows people to chain assignments, as you can with fundamental types.
However, that will only work if the assignment operator takes its argument by value or const reference; yours takes it by non-const reference, which is something you should only do in special circumstances.
circle & operator=(circle const & c) {
radius = c.radius;
x = c.x;
y = c.y;
return *this;
}
With an operator like that, c4=c2=c1 will compile, and will have the effect of assigning c1 to c2, then assigning the new value of c2 to c4.
It's to support the idiom of a = b = c.
You're also doing it wrong; the return should be circle & not circle and the return should be return *this;.
You can just return *this from your assignment operator function to return a reference to the current object. You can also make the value of the
circle& operator = (circle& c)
{
// do assignments
return *this;
}