I have to create a Complex class and a vector class that includes vectors of Complex numbers. I have to overload +,-,/,*, << in both classes. Would they both be member functions or would it be easier to put them as nonmember functions? In addition, is there a way to make the vector class only have the vector as a parameter, rather than including the real and imaginary number and vector? The following code from is my class member functions of the vector class.
class ComplexVector : public Complex //vectors whose elements are complex numbers
{
public:
ComplexVector();
ComplexVector(double real, double imaginary, std::vector <Complex> vec);
ComplexVector(std::vector <Complex> vec);
friend ComplexVector operator+ (const ComplexVector& v1, const ComplexVector& v2);
friend ComplexVector operator- (const ComplexVector& v1, const ComplexVector& v2);
friend ComplexVector operator* (const ComplexVector& v1, const ComplexVector& v2);
friend ComplexVector operator/ (const ComplexVector& v1, const ComplexVector& v2);
int get_size() const;
private:
std::vector <Complex> cvec;
};
std::ostream& operator<< (std::ostream& stream, const ComplexVector& comvec);
I put the explanations of each function in a separate cpp file. Even though I used friend in the header file, on the cpp file it says that i am not allowed to use two parameters. Is there a way to get out of that? In addition, would I have to use pointers in order to access what is in the vector? I have heard of using vector but I have tried and the arithmetic doesn't make sense to me. (Note: I was playing around so not all the code is exactly correct) Thanks!
ComplexVector::ComplexVector() : Complex() {}
ComplexVector::ComplexVector(double real, double imaginary, std::vector<Complex> vec) : Complex(real, imaginary), cvec(vec) {}
ComplexVector::ComplexVector(std::vector<Complex>vec) {cvec = vec;}
ComplexVector& ComplexVector::operator+ (ComplexVector v1, const ComplexVector& v2)
{
std::vector <Complex> add;
for (int i = 0; i < v1.get_size(); i++)
{
double xside = v1[i].get_real() + v2[i].get_real();
double yside = v1[i].get_()imaginary + v2[i].get_imaginary();
add[i] = Complex(xside,yside);
}
ComplexVector add_sol(add);
return add_sol;
}
ComplexVector ComplexVector::operator- (const ComplexVector& v1, const ComplexVector& v2)
{
std::vector <Complex> sub;
for (int i= 0; i < v1.get_size(); i++)
{
sub[i] = v1[i] - v2[i]; //same as +?
//does not provide subscript operator????
}
ComplexVector sub_sol(sub);
return sub_sol;
}
ComplexVector ComplexVector::operator* (const ComplexVector& v2)
{
ComplexVector multi;
for (int i = 0; i < v1.size(); i++)
{
multi[i] = v1[i] * v2[i];
}
return multi;
}
ComplexVector operator/ (const ComplexVector& v2)
{
ComplexVector div;
for (int i = 0; i < v1.size(); i++)
{
div[i] = v1[i] / v2[i];
}
return div;
}
int ComplexVector::get_size() const
{
int total;
for (int i = 0, i < cvec.size(); i++)
{
total++;
}
return total;
}
std::ostream& ComplexVector::operator<< (std::ostream& stream, const ComplexVector& comvec)
{
for (int i = 0; i < comvec.size(); i++)
{
stream << comvec[i] -> get_real() << " " << "+" << " " << comvec[i] -> get_imaginary() << "i" ;
}
return stream;
}
Operators defined in the class:
If a class declares the operator + as follow:
class A {
public:
A operator+(A b);
};
It means that the b is the second operand, the first being the object on which the operator is invoked. Otherwise said, with x, y and z being of class A:
z = x + y;
is equivalent to:
z = x.operator+(y);
Unfortunately the ComplexVector:: in the following definition indicates that you are defining the operator as class member:
ComplexVector& ComplexVector::operator+ (ComplexVector v1, const ComplexVector& v2)
The thing is that operator+ takes two operands. In this case it'll be the object itself and v1. So the compiler complains about the second argument that is explicitly declared, which would be the third operand of operand+. which is illegal.
Friend operators defined outside the class
If you define a friend operator like:
class A {
public:
friend A operator-(A a, A b);
};
it means that the operator- is not a class member but an independent operator. As such it needs two arguments for an operation to occur. So
z = a - b;
would be equivalent to
z = ::operator- (a, b);
Unfortunately you do not use that approach in your code.
Other remarks
You need to declare the operators according to some general rules, so that they keep a semantic of the natural operators.
As such for +, -, * and / you should not take arguments by reference (or eventually a const reference) and you should always return by value, including for operator+.
Here a step by step article by Herb Sutter to explain more in details some constraints around operator overloading. Here a more advanced guideline.
Finally, without wanting to be rude, what's the logic of making a vector of complex inherit from a complex ? A vector of complex is not a kind of complex. It's a completely different class, with a dependency relationship, but there's absolutely no justifiable reason for the inheritance ! Or is there ?
Related
Consider a simple vector class realization:
#include <algorithm>
class Vector {
public:
Vector(int _elementsCount)
: elementsCount(_elementsCount)
, elements(new float[_elementsCount])
{}
~Vector() {
delete[] elements;
}
Vector(const Vector& rhs) {
elementsCount = rhs.size();
elements = new float[elementsCount];
for (int i = 0; i < elementsCount; ++i)
(*this)[i] = rhs[i];
}
float& operator [](int i) {
return elements[i];
}
float operator [](int i) const {
return const_cast<Vector&>(*this)[i];
}
int size() const {
return elementsCount;
}
/*// Dot product
float operator *(const Vector& v) {
float res = 0;
for (int i = 0; i < size(); ++i)
res += (*this)[i] * v[i];
return res;
}*/
private:
int elementsCount;
float* elements;
};
// Multiplication by a scalar
Vector operator *(const Vector& v, float k) {
Vector res(v.size());
for (int i = 0; i < v.size(); ++i)
res[i] = v[i] * k;
return res;
}
// Dot product
float operator *(const Vector& v1, const Vector& v2) {
float res = 0;
for (int i = 0; i < std::min(v1.size(), v2.size()); ++i)
res += v1[i] * v2[i];
return res;
}
void main()
{
Vector v(2);
v * 3; // ambiguous
}
This code compiles. But if we uncomment * operator realization in the class and comment its global realization (dot product function), then there will be an error "'Vector::operator *': 2 overloads have similar conversions", because there is an ambiguity: whether to call the multiplication by a scalar or to interpret 3 as an argument to a parametrized constructor and to call the dot product. This makes sense. But I don't get what's the difference of declaring the * operator as a member function or as a global function. I thought they should be the same in the example like above, but it's not the case.
Added. The thing I most interested in is not how to avoid the ambiguity, but why there is an ambiguity in one case (when * is declared as a member) and there is no one in the other (when * is declared as a global function).
You need to make your constructor explicit:
explicit Vector(int _elementsCount) { ... }
The reason for the ambiguity is that the compiler can't decide whether it should implicitly convert a int value to a Vector and invoke Vector::operator*, or implicitly convert a int value to a float and use operator*(const Vector&, float).
By using explicit, such conversions are forbidden, and you must use Vector(3) if you want "3" to be a Vector.
As a side-note, you should make the operator const, since it does not modify the object. Making it const will also allow it to be used with a const Vector:
float operator *(const Vector& v) const { ... }
Beware that will still conflict with your other overload:
float operator *(const Vector& v1, const Vector& v2)
There is no reason to have both. Choose either the member function or the global function and remove the other.
The detailed discussion of the problem is shown in this link. I am trying to sum up two instance variable defined inside class Point and assign it to a different variable temp.
class Point{
public:
double x;
double y;
friend istream& operator>>(istream& input, Point& p);
double operator=(Point& p);
double getSqX(void);
double getSqY(void);
double LengthSquared(void);
};
double Point::getSqX(void){
return pow(x,2);}
double Point::getSqY(void){
return pow(y,2);}
double Point::LengthSquared(){ return getSqX() + getSqY(); }
istream& operator>>(istream& input, Point& p){
... // over load the >> operator
return input;
};
int main(){
double temp;
vector<vector<Point> > FFTfile= some function that loads data();
for (int i = 0; i < FFTfile.size(); i++){
for (int j = 0; j < FFTfile[i].size(); j++){
temp=FFTfile[j].LengthSquared();
}
}
return(0);
}
Edit:
Based on the suggestions, I created a method LengthSquared(), but I still get following error:
error: 'class std::vector<Point>' has no member named 'LengthSquared' temp=FFTfile[j].LengthSquared();
You should never overload the assignment operator this way. Someone reading your code will be confused, since assignment normally means .. assign value to object.
Instead, create a method like this
double Point::LengthSquared() { return getSqX() + getSqY(); }
an assignment-operator should have the following interface:
Point& operator=(const Point& other);
or
Point& operator=(const AnotherType& other);
to allow assignments of other types.
You are abusing the assignment operator. Use a regular method.
I need your help, please have a look at the following code I get error
as following:
no match for operator *(operand types are'doubles and 'lists')
this is inherited class, header file(before operator* function it worked properly)
class lists:public vectorebi
{
public:
lists (double first_);
lists (double first_, lists var_);
double operator-(const double& answer);
lists operator*(const lists &answer) const;
virtual ~lists(){};
private:
friend std::ostream& operator<<(std::ostream& os, lists& arg);
double first;
lists* var;
};
//soucre file
lists::lists(double first_){
first=first_;
}
lists::lists(double first_, lists var_){
first=first_;
var=&var_;
}
double lists::operator-(const double& answer){
double result = answer - first;
return result;
}
lists lists::operator*(const lists &answer) const
{
lists k = first * answer.first;
return k;
}
std::ostream& operator<<(std::ostream& os, lists& arg) {
os << "(" << arg.var << ")";
return os;
}
and the main ///
int main()
{
double answer1 = 15;
lists k=5;
lists answer = k * answer1; //here is an error as compiler points
cout << answer;
return 0;
}
I will appreciate your help, I am trying to multiply variable of type my class and double, is it possible?
* is a binary operator, meaning it expects 2 arguments.
When you say a * b, a becomes the first (left) argument and b becomes the second (right) argument. Effectively the function call looks like a.operator*(b).
You are doing, answer1 * k which evaluates to the call answer1.operator*(k) . This means double must have operator* overloaded for lists.
But you want it for your class lists. So you must do this in main():
lists answer = k * answer1;
And operator* must be declared as:
lists lists::operator*(const double& answer)
{
lists k = first * answer; // not sure how double * double equals lists
return k;
}
EDIT:
Regarding the error
lists* lists::var is private within this context
which you pointed out in the comments, it appears because of the inconsistent declaration of friend operator<<.
You have declared it as:
friend std::ostream& operator<<(std::ostream& os, const lists& arg); // note the `const` for `arg`
But you have defined it as:
std::ostream& operator<<(std::ostream& os, lists& arg) // `const` missing!!
{
....
}
Just add const in the definition as well, and it will work as expected.
The line:
lists answer = answer1 * k;
fails because the compiler is looking for a * overload on a double that takes lists instance. This method doesn't exist, but you can define it my creating the method outside your class:
lists operator*(double lhs, const lists &rhs)
{
return lists(lhs) * rhs;
}
NOTE: I've made rhs a const as this is best practice for operator overloads like this which do not (and should not) modify their inputs:
lists operator*(const lists &answer) const;
in the declaration and:
lists lists::operator*(const lists &answer) const
{
lists k = first * answer.first;
return k;
}
in the implementation.
NOTE: I think you meant to multiple by answer.first and otherwise the code doesn't make much sense.
Also, your streaming operator currently tries to output var which is a member variable you never initialize. I suspect you want to output first so change it to this:
std::ostream& operator<<(std::ostream& os, const lists& arg)
{
os << "(" << arg.first << ")";
return os;
}
I've made arg const as this is the recommended practice. You'll need to update your class definition to reflect this.
Writing my own vector class (for a game engine) and overloading '+' operator in Visual Studio 2013 CPlusPlus project (using VC runtime 120), it is throwing me compiler error:
Error: too many parameters for this operator function.
Code snippet from Vector.hpp file below.
Vector.hpp
class Vector
{
private:
double i;
double j;
double k;
public:
Vector(double _i, double _j, double _k)
{
i = _i;
j = _j;
k = _k;
}
Vector& operator+=(const Vector& p1)
{
i += p1.i;
j += p1.j;
k += p1.k;
return *this;
}
//Some other functionality...
Vector operator+(const Vector& p1, Vector& p2) //Error is thrown here...
{
Vector temp(p1);
return temp += p2;
}
};
What am I doing wrong here? Don't want to make my operator overload non-member function.
When operator+ is defined inside class, left operand of operator is current instance. So, to declare a overload of operator+ you have 2 choices
inside class, with only one parameter which is right operand
outside of class, with two parameters, left and right operands.
Choice 1: outside class
class Vector
{
private:
double i;
double j;
double k;
public:
Vector(double _i, double _j, double _k)
{
i = _i;
j = _j;
k = _k;
}
Vector& operator+=(const Vector& p1)
{
i += p1.i;
j += p1.j;
k += p1.k;
return *this;
}
//Some other functionality...
};
Vector operator+(const Vector& p1, const Vector& p2)
{
Vector temp(p1);
temp += p2;
return temp;
}
Choice 2: inside class
class Vector
{
private:
double i;
double j;
double k;
public:
Vector(double _i, double _j, double _k)
{
i = _i;
j = _j;
k = _k;
}
Vector& operator+=(const Vector& p1)
{
i += p1.i;
j += p1.j;
k += p1.k;
return *this;
}
Vector operator+(const Vector & p2)
{
Vector temp(*this);
temp += p2;
return temp;
}
};
You can see how should be declared operators here : C/C++ operators
one more possibility is by using the friend keyword.
friend Vector operator+(const Number& n1, const Number& n2)
{
Vector temp(n1);
temp+=n2;
return temp;
}
Let's say I have a class Number
class Number
{
public:
int numb;
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
};
And when I try to use my overloaded operator
cout << 3 + s; // doesn't work
cout << s + 3;
I understand why it doesn't work, but I don't know how to make it work for 3 + s
Of course, I can write operator+ with 2 arguments outside the class, but I want to have my operator overloaded in the class.
I've googled it, but didn't find any solution.
Easiest way to go: write another overload outside of your class
class Number
{
public:
int numb;
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
};
int operator+(int h, Number& n)
{
return n.numb+h;
}
int main()
{
int s = 42;
std::cout << 3 + s;
std::cout << s + 3;
}
Live Example
This also works if your data is private (but make sure the outside function has access to those members)
class Number
{
int numb;
public:
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
friend int operator+(int, Number&);
};
int operator+(int h, Number& n)
{
return n.numb+h;
}
Of course, I can write operator+ with 2 arguments outside the class, but I want to have my operator overloaded in the class.
This is like saying "Of course I could hammer in my nail with a hammer, but I want to use a screwdriver..."
Some other solutions suggested using both a member and a non-member, but that is redundant: if you add the non-member then you no longer need the member!
The proper way to overload operator+ is to use the non-member:
Number operator+(Number a, Number b)
{
return a.numb + b.numb;
}
Another way to write this is to use operator+= as a helper (then your class will support += too):
Number operator+(Number a, Number b)
{
return a += b;
}
with member function:
Number &operator+=(Number b)
{
numb += b.numb;
return *this;
}
You could either make operator+ return Number or int, your choice.
Just write an operator outside the class that calls the one in your class!
template<typename T> T operator+(T a, Number& n)
{
return n+a;
}