### How to Overload Operators with Polymorphism

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.

 ``1234567891011121314151617`` ``````class ComplexVector : public Complex //vectors whose elements are complex numbers { public: ComplexVector(); ComplexVector(double real, double imaginary, std::vector vec); ComplexVector(std::vector 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 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!

 ``12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061`` ``````ComplexVector::ComplexVector() : Complex() {} ComplexVector::ComplexVector(double real, double imaginary, std::vector vec) : Complex(real, imaginary), cvec(vec) {} ComplexVector::ComplexVector(std::vectorvec) {cvec = vec;} ComplexVector& ComplexVector::operator+ (ComplexVector v1, const ComplexVector& v2) { std::vector 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 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; }``````
Last edited on
> `class ComplexVector : public Complex`
¿are you sure about that inheritance?
¿what are you doing with the `real' and `imaginary' members that were inherit from `Complex?

> `friend ComplexVector operator+ (const ComplexVector& v1, const ComplexVector& v2);`
there you are declaring a non-member function

> `ComplexVector& ComplexVector::operator+ (ComplexVector v1, const ComplexVector& v2)`
there you are defining a member function.
that's why it's complaining about «not allowed to use two parameters» (remember that being a member function you also have `this`)

Also, note that you are changing the prototype. You are returning a reference (to a local variable even) and passing the first parameter by copy instead of const reference.

> Would they both be member functions or would it be easier to put them as
> nonmember functions?
overload +=, -=, /=, *=, as member functions
define +, -, /, *, as non-friend non-member function
 ``123`` ``````ComplexVector operator+(ComplexVector a, const ComplexVector &b){ return a += b; }``````

For <<, notice that the left side is not your class, but ostream
so you can't make it a member function (as you don't have access to ostream code)
if you need it to be friend or not, would depend on the interface of your class.

> 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
sorry, not follow.
focus on just one operator and make your code compilable, then show your issue.
I took off the inheritance of Complex in ComplexVector.
I must have missed the small part in my question. Would I have to use pointers in order to access what is in the vector. I have heard of using std::vector<Complex*> but I have tried and the arithmetic doesn't make sense.

Do I keep the operator overload functions in the class?

 ``1234567891011121314151617181920212223242526272829303132333435`` ``````class Complex //Complex numbers are expressed in the form a + bi, where a is the real part, b is the imaginary part, and i is the imaginary unit satisfying i2 = -1. { public: Complex(); Complex (double r, double i); Complex operator+ (const Complex& c2); Complex operator- (const Complex& c2); Complex operator* (const Complex& c2); Complex operator/ (const Complex& c2); double get_real() const; //declared double get_imaginary() const; //declared private: double real; double imaginary; }; std::ostream& operator<< (std::ostream& stream, const Complex& comvec); class ComplexVector //vectors whose elements are complex numbers { public: ComplexVector(); ComplexVector(std::vector vec); friend ComplexVector operator+ (ComplexVector v1, const ComplexVector& v2); friend ComplexVector operator- (ComplexVector v1, const ComplexVector& v2); friend ComplexVector operator* (ComplexVector v1, const ComplexVector& v2); friend ComplexVector operator/ (ComplexVector v1, const ComplexVector& v2); int get_size() const; private: std::vector cvec; }; std::ostream& operator<< (std::ostream& stream, const ComplexVector& comvec);``````

I changed the cpp file as well. I keep getting the notification of "Type 'ComplexVector' does not provide a subscript operator" and "Type 'const ComplexVector' does not provide a subscript operator". I thought i was able to use [] because I am going through a vector.

 ``12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970`` ``````ComplexVector::ComplexVector() {} ComplexVector::ComplexVector(std::vector vec) {cvec = vec;} ComplexVector operator+ (ComplexVector v1, const ComplexVector& v2) { std::vector 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] = new Complex(xside,yside); } ComplexVector add_sol(add); return add_sol; } ComplexVector operator- (ComplexVector v1, const ComplexVector& v2) { std::vector sub; for (int i= 0; i < v1.get_size(); i++) { double xside = v1[i].get_real() - v2[i].get_real(); double yside = v1[i].get_real() - v2[i].get_real(); sub[i] = new Complex(xside,yside); //does not provide subscript operator???? } ComplexVector sub_sol(sub); return sub_sol; } ComplexVector operator* (ComplexVector v1, const ComplexVector& v2) { std::vector multi; for (int i = 0; i < v1.get_size(); i++) { double xside = (v1[i].get_real() * v2[i].get_real) - (v1[i].get_imaginary() * v1[i].get_imaginary); double yside = (v1[i].get_real() * v2[i].geT_imaginary) + (v2[i].get_real * v1[i].get_imaginary; multi[i] = new Complex(xside, yside); } ComplexVector multi_sol(multi); return multi_sol; } ComplexVector operator/ (const ComplexVector& v2) { std::vector div; for (int i = 0; i < v1.get_size(); i++) { double xside = ((v1[i].get_real() * v1[i].get_imaginary()) + (v1[i].get_imaginary() * v2[i].get_imaginary())) / ((v2[i].get_real() * v2[i].get_real()) + (v2[i].get_imaginary * v2[i].get_imaginary()))); double yside = ((v1[i].get_imaginary() * v2[i].get_real()) - (v1[i].get_real() * v2[i].get_imaginary())/ (v2[i].get_real() * v2[i].get_real() + (v2[i].get_imaginary() * v2[i].get_imaginary()))); div[i] = new Complex(xside, yside); } ComplexVector div_sol(div); return div; } int ComplexVector::get_size() const { int total; for (int i = 0, i < cvec.size(); i++) { total++; } return total; } //ComplexVector nonmember 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; }``````
> std::vector<Complex*>
don't do that, there is no benefit over `std::vector<Complex>`
you are simply increasing the complexity of your program, as now you've got to do memory management.

> I thought i was able to use [] because I am going through a vector.
`cvec' is a vector, you can use [] on `cvec'
 ``123456`` ``````ComplexVector& ComplexVector::operator+= (const ComplexVector& v2){ for (int K = 0; K < this->cvec.size(); K++) this->cvec[K] += v2.cvec[K]; //using the operator+= of `Complex' return *this; }``````

notice that I've defined operator+=, and that used the operator+= of Complex (you don't have it, you have operator+)

perhaps you do want the client code to use [] on your ComplexVector, then you need to provide that member function (both const and nonconst versions)
 ``1234567`` ``````Complex& ComplexVector::operator[](int index){ //as a member function return this->cvec[index]; } const Complex& ComplexVector::operator[](int index) const{ //to work with const objects return this->cvec[index]; }``````

By the way, if a member function does not modify the state of its object, declare it const so it can work with constant objects
`Complex operator+ (const Complex& c2) const; `
> I have to overload +,-,/,*, << in both classes.
> Would they both be member functions or would it be easier to put them as nonmember functions?

 Canonical implementations Commonly overloaded operators have the following typical, canonical forms: Stream extraction and insertion The overloads of operator>> and operator<< that take a std::istream& or std::ostream& as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument (b in a@b), they must be implemented as non-members. Binary arithmetic operators Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex+integer would compile, and not integer+complex). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments. http://en.cppreference.com/w/cpp/language/operators

For example, using std::complex<double> (instead of a custom complex class) for brevity:

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051`` ``````#include #include #include using complex = std::complex ; struct complex_vector : private std::vector { using std::vector::vector ; using std::vector::operator= ; using std::vector::size ; using std::vector::empty ; // etc. // implement overloaded compound assignment operators (member functions) complex_vector& operator+= ( const complex_vector& that ) { resize( std::max( size(), that.size() ) ) ; for( std::size_t i = 0 ; i < that.size() ; ++i ) (*this)[i] += that[i] ; return *this ; } // likewise for -=, *=, /= complex_vector& operator-= ( const complex_vector& that ) ; complex_vector& operator*= ( const complex_vector& that ) ; complex_vector& operator/= ( const complex_vector& that ) ; // implement overloaded arithmetic operators in terms of the corresponding // compond assignment operator. note that the first argument is passed by value // this is canonical. see Canonical implementations: Binary arithmetic operators // in http://en.cppreference.com/w/cpp/language/operators friend complex_vector operator+ ( complex_vector a, const complex_vector& b ) { return a += b ; } friend complex_vector operator- ( complex_vector a, const complex_vector& b ) { return a -= b ; } friend complex_vector operator/ ( complex_vector a, const complex_vector& b ) { return a /= b ; } friend complex_vector operator* ( complex_vector a, const complex_vector& b ) { return a *= b ; } // overloaded stream insertion operator can't be a member function friend std::ostream& operator<< ( std::ostream& stm, const complex_vector& vec ) { stm << "[ " ; for( const complex& c : vec ) stm << c << ' ' ; return stm << ']' ; } }; int main() { const complex_vector a( 6, complex{ 1.01, 2.34 } ) ; const complex_vector b { {1.12,2.23}, {3.34, 4.45}, {5.56,6.67} } ; std::cout << a << " +\n" << b << " ==\n" << a+b << '\n' ; }``````

http://coliru.stacked-crooked.com/a/3cbaa87a9802c3e7