virtual Operator overloading - c++

I am making a GVector class that contains will further derive into 3 types i.e
PVector (Pixel Space Vector)
MVector (Meter Space Vector)
RVector (Rendering Space Vector)
class GVector {
public :
eVectorSpace eVS; // Defines which space the vector would be
float x,y; // The x and y values of a 2-Dimensional vector
...
GVector operator+ (const GVector& v) const { return GVector(x+v.x, y+v.y, v.eVS); }
...
};
class MVector {
public :
PVector toPVector() {...}
//Will contain functions to convert the same vector into a different space
};
I want to make it possible to add 2 vectors lying in the same space
MVector operator+ (const MVector& v) const { return MVector(x+v.x, y+v.y); }
Do I need to make the base class function like this ?
virtual GVector* operator+ (const GVector* v) const () = 0;
But I would like to return a vector in the same space as the two adding vectors.
The function of adding the values of the x,y are same for each type of vector.
Is there a way to minimize this into the base class itself ?
Or is there a better approach to adding vectors in the same space and converting them into different spaces ?

If it makes no sense to perform operations on two different children then the operator should not be defined on the parent. Instead a protected helper function can be defined, and then the children should implement the operator separately, delegating to the helper function.

Some code somewhere needs to know how to add two of the vector objects together, but it doesn't actually need to be the vector types themselves. You can define a set of addition operators outside the classes.
MVector operator+(const MVector &left, const MVector &right) {
return MVector(left.x + right.x, left.y + right.y);
}
You can define as many different operator adds like this as you want, so long as the compiler can figure out what the types are without ambiguity. You can even provide implementations that accept a MVector and a GVector.
MVector operator+(const MVector &left, const RVector &right) {
MVector tmp = right.toMVector();
return MVector(left.x + tmp.x, left.y + tmp.y);
}

Related

Declaration inside class or outside?

Given the following functions:
1)
IntMatrix operator+(const IntMatrix &matrix, int scalar);
2)
IntMatrix operator+(int scalar, const IntMatrix &matrix);
Which take a scalar and adds it to every member in the Matrix, Should I declare them outside the class (like what is shown above) or inside my class?
In collage they thought as that if we need it to work in both directions (symmetrical behaviour) we declare it out but here it's a little bit complicated...
Function 1 can be written inside the class, as a member function, but function 2 must be written as a non-member function, since the left hand side is not a IntMatrix.
I would suggest writing a operator+= that takes an int as a member function. Then you can easily call that from both operator+, which you can write as non-members.
So your operator+ (as non-members) would look like this:
IntMatrix operator+(IntMatrix matrix, int scalar) {
return matrix += scalar;
}
IntMatrix operator+(int scalar, IntMatrix matrix) {
return matrix += scalar;
}

performing function with classes of similar type C++

I want to implement a representation of matrices.
for that I have two types of matrices - regular and sparse, which differ in their
implementation - one holds a vector, and the second a map of indices and value,
both inherit from Matrix class.
I want to implement the + operator, which operates on Matrix and receives another Matrix.
but when I implement the + operator, I might receive as parameter sparse/regular matrix.
is there any way to receive a matrix, which I don't know what type of the 2 it is,
and perform the + operator?
meaning, if in class SparseMatrix I receive sparse/regular matrix, how can I implement the operator such that no matter which of the two types I get, it will work?
Matrix & operator+ (Matrix other)
{
...
}
I would probably implement two versions of operator+, and let them call a helper template method:
template <typename ITER>
Matrix add (ITER other_it) {
//...
}
Matrix operator+ (RegularMatrix other)
{
return add(other.begin());
}
Matrix operator+ (SparseMatrix other)
{
return add(other.begin());
}
You could make operator+ a template, but this way makes sure you only allow those Matrix types.
As was pointed out to me, you should not return a reference from +, as the result needs to be point to an instance that exists after the operation returns.
We can use polymorphism to create different implementations of a Matrix. Through the common interface of Matrix, each implementation can interact.
class Matrix
{
class iterator { ... }
friend Matrix operator+(const Matrix &lhs, const Matrix &rhs)
{
// iterate, add, and return new matrix
}
};
class SpareMatrix : public Matrix
{
iterator begin() { ... }
};
class Matrix
{
public:
virtual ~Matrix() {}
virtual Matrix& operator+(Matrix& other) = 0;
};
class MatrixSparse : public Matrix
{
public:
virtual ~MatrixSparse() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixSparse* sparse = dynamic_cast<MatrixSparse*>(&other);
// TODO
}
};
class MatrixRegular : public Matrix
{
public:
virtual ~MatrixRegular() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixRegular* regular = dynamic_cast<MatrixRegular*>(&other);
// TODO
}
};
Also, here is another SO thread dealing with the problem of overloading operators from abstract classes.

Using sets and overloading operators in C++

So for class this week I have to use a set to read in the Declaration of Independence and the US Constitution from a .txt file, store them in sets, and overload operator* to find and return the intersection of the two sets.
Reading everything in is not a problem, neither is finding out the intersection in the sets. What I'm having a lot of trouble with is overloading operator*. I keep getting two errors:
no operator "*" matches these operands
and
binary "*":'std::set<_Kty>' does not define this operator or a conversion to a type acceptable to the predefined operator
Here is my code so far:
From main:
Reader r;
std::set<std::string> d, c;
d = r.GetDeclaraton();
c = r.GetConstitution();
Set dec(d), con(c);
Set intersection = dec * con;
The errors are coming from that last line of main.
From Set.h
class Set
{
public:
std::set<std::string> s;
Set(void);
Set(std::set<std::string> set)
{
s = set;
}
~Set(void);
std::set<std::string> operator* (const std::set<std::string> &rhs)
{
std::set<std::string> newset;
std::set<std::string>::iterator rhsiter = rhs.begin(), result;
while (rhsiter != rhs.end())
{
result = s.find(*rhsiter++);
if (result != rhs.end())
{
newset.insert(*result);
}
}
return newset;
}
};
You need
Set operator* (const Set &rhs) const
because this is a binary operator with two Sets as arguments. Your attempt would only work if your Set was deriving std::set.
The return type here is Set. It makes more sense to be the same as the input arguments, and this is also consistent with your usage in main. So in this case you need to modify the definition to construct and return a Set instead of an std::set (or rather you need not because an std::set can be implicitly converted to a Set).
Note also I made operator* a const member function, since it's not modifying its object.
operator* is defined in your custom Set so the left-hand-side argument must be a Set, but in dec.s * con.s you're using .s which accesses the member std::set fields, and there's no operator* defined for a left-hand Set and rhs-hand std::set.
You could change to dec * con.s, but it'd be better to change the operator* rhs argument to a const Set& too, and use rhs.s inside the operator... less confusing!
In my opinion its better to write a global or friend operator. Also, for intersection I would use the & operator, for union the | or + operator while, difference: -...
Why global operators? With global operators you can write an operator for your class even if the left operand is not your class. For example in case of a matrix class you can easily write a global operator that multiplies together a float and a matrix while as a matrix member operator you could write only an operator where your matrix is on the left.
Example:
template <typename T>
inline std::set<T> intersection(const std::set<T>& smaller, const std::set<T>& larger)
{
std::set<T> result;
for (auto it=smaller.begin(),eit=smaller.end(); it!=eit; ++it)
{
if (larger.find(*it) != larger.end())
result.insert(*it);
}
return result;
}
template <typename T>
inline std::set<T> operator & (const std::set<T>& a, const std::set<T>& b)
{
if (a.size() < b.size())
return intersection(a, b);
return intersection(b, a);
}
class Set
{
public:
std::set<std::string> s;
Set() {}
Set(std::set<std::string> _s) : s(_s) {}
friend Set operator & (const Set& a, const Set& b)
{
return Set(a.s & b.s);
}
};
int test()
{
std::set<std::string> s, t;
s.insert("aa");
s.insert("bb");
t.insert("bb");
t.insert("cc");
std::set<std::string> u(s & t);
Set ss(s), st(t);
Set result(ss & st);
return 0;
}

Constructing result in operator vs operating on default-constructed object

I have a class which is essentially an array with labelled contents, and I'd like to define some operators for it. I'd like to do it in such a way that changing the number of elements in the class is easy, as I expect future users will change the variables tracked, but I'd also like to ensure that basic arithmetic operations on the class are as efficient as possible.
I can see two way of implementing the operators. Taking the example of a Vector2D class:
struct Vector2D {
//members
const static int nElem = 2;
double x;
double y;
//Constructors
Vector2D() {}
Vector2D(double X, double Y) : x(X), y(Y) {}
//Operators
double& operator[] (int index) {
switch(index) {
case 0:
return x;
case 1:
return y;
default:
return std::out_of_range ("Oops");
}
}
// Option 1: operator+ by constructing result
Vector2D operator+ (const Vector2D & rhs) const {
return Vector2D(x + rhs.x, y+rhs.y);
}
// Option 2: operator+ using loop and [] operator
Vector2D operator+ (const Vector2D & rhs) const {
Vector2D result;
for(int i = 0; i < nElem; i++)
result[i] = (*this)[i] + rhs[i];
return result;
}
};
Assuming I use -03 optimization, will there be any difference between the two implementations of operator+? My understanding is that since the default Vector2D constructor has no code body and the class contents are a default data type, there is no extra overhead in Option 2 for calling the default constructor on result before setting its members. I expect the two to be equivalent, but I'm not confident enough in my knowledge to be sure.
Your method won't work at all. If you want someone to be able to change nElem you can't use x, y as your names. Why? Because changing nElem to 3 won't magically add z. And since you can't do a for loop over x and y, your definition of nElem is meaningless.
Finally, this is a textbook case for the use of a number template. Create a vector which is templated over how many elements it has.
Do something like this:
template<unsigned int LEN>
class Vector{
double v[LEN];
public:
Vector operator+(const Vector &o){
Vector res;
for (unsigned int i=0;i<LEN;++i) // with -O3 and small LEN this will be unrolled
res.v[i]=v[i]+o.v[i];
}
// ... etc.
};
Then you use it like this:
Vector<2> my_2d_vec;
Vector<3> my_3d_vec;

Templated Vector and Colour Maths library (Specialisation)

I have created a maths library that operates via templates, it allows the user to specify the size and type of the array within a class which is then used to create a maths vector of any dimension up to four. As soon as I went to create a colour class, it struck me how similar the vector and colour class are. Is there anyway in which I could reduce code reuse and use some form of inheritance or specialisation to separate:
Specific functionality (ie vector3 does not have a setXYZW() function, instead only a setXYZ()) to the dimension of which it can only be used in.
Colour class and vector class can both (in terms of array data member) be of size ranging from 1 to 4 and the both share the same operators, but differ in their use in some circumstances such as a multiply vector differs from a multiply colour.
My knowledge of templates is not that good, so I would very much appreciate if anyone can show me the best solution to such a situation?
template < std::size_t N = 3, typename T = float >
class Vector
{
typedef T Degree, Radian;
private:
T m_vecEntry[N];
public:
// arithmetic operations
Vector operator + (const Vector & _vector) const;
Vector operator - (const Vector & _vector) const;
Vector operator * (const Vector & _vector) const;
Vector operator * (float _val) const;
};
template < std::size_t N = 4, typename T = float >
class Colour
{
private:
T m_colEntry[N];
public:
// arithmetic operations
Colour operator + (const Colour& _colour) const;
Colour operator - (const Colour& _colour) const;
Colour operator * (const Colour& _colour) const;
Colour operator * (float _val) const;
};
Your classes have a fair amount of duplicated code, it is advisable that you do something about it. A possible solution follows.
First, you take the common functionality to a base class:
template <class Derived, std::size_t N, typename T>
class VectorBase
{
protected:
VectorBase() {} // Prevent instantiation of base
Derived operator + (const Derived & _vector) const {
std::cout << "Base addition\n";
return Derived();
}
Derived operator * (T _val) const {
std::cout << "Base scalar multiplication\n";
return Derived();
}
T m_components[N];
};
Then you derive from it your Vector and Colour classes. In each derived class you use using Base::operation; to state explicitly that the corresponsing operation from the base class makes sense in the derived class.
For operations that don't make sense in the derived class you provide an alternative definition or not provide it at all (it will not be accessible since you didn't write using).
You can also add operations that were not in the base class, like Vector::norm:
template < std::size_t N = 3, typename T = float >
class Vector : VectorBase<Vector<N, T>, N, T>
{
typedef VectorBase<Vector<N, T>, N, T> Base;
typedef T Degree, Radian;
public:
using Base::operator+; // Default implementation is valid
using Base::operator*; // Default implementation is valid
T norm() const { // Not present in base class
return T();
}
};
template < std::size_t N = 4, typename T = float >
class Colour : VectorBase<Colour<N, T>, N, T>
{
typedef VectorBase<Colour<N, T>, N, T> Base;
public:
using Base::operator+; // Default implementation is valid
Colour operator * (T _val) const { // Redefines version in base class
std::cout << "Colour scalar multiplication\n";
return Colour();
}
};
The only trick in this code is that I've used the CRTP to make base class operations work with derived types.
Here is a little test program:
int main()
{
Vector<> va, vb;
va + vb;
va.norm();
va * 3.0;
Colour<> ca, cb;
ca + cb;
ca * 3.0f;
}
It prints:
Base addition
Base scalar multiplication
Base addition
Colour scalar multiplication
Ultimately the compiler will only create the parts of the template specialization it determines you are going to use. So it in affect will do the optimization for you e.g. not creating an unused method and so on.
So you may just want to consider making normal pre-processor macros to wrap the slight tweaks per template.
But obviously if you want to make some specializations you can do that too, but you'll still end up duplicating lines of code as it were ;)
A lot of graphic engines keep the two separate for precisely the reasons you mentioned. While the structure of the data is equal both require different semantics for operations on the data. This also has the added benefit of more meaningful function names (setX vs setRed) but means code duplication.
Your implementation is just a wrapper around fixed size arrays. You could move the data and shared functionality in a (possible abstract) base class and provide the specific functionality in child classes.
Another way would be to treat your vector and colour classes as decorators to an array wrapper. Write or use a wrapper around arrays and combine it with vector/color functionality through composition.