HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Creating n-dimensional mathematical vector classes through inheritance

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
creatinginheritanceclassesthroughdimensionalvectormathematical

Problem

Right now I have no knowledge of templates, but I just finished learning about inheritance, and wanted to apply it to a Vector3 class that I had already created. My thoughts were that vectors of different dimensions share some common operations, and so it should be possible to apply an inheritance hierarchy to this.

Ultimately I might want a program that can operate with vectors without knowing their dimension. As a result, all vectors inherit from an abstract base class Vector which contains the most general operations of vectors for all dimensions, such as normalise(), get_length() a bool conversion and > operators.

I've included just the header because I'm really concerned only with making sure my inheritance structure is adequate. The function definitions would take up a lot of room, and I don't think they are too important (although let me know if they are necessary).

Vector.h

```
#ifndef MATHSVectors
#define MATHSVectors

#include
#include //pair

class Vector{ //abstract base class but we do expect users, so virtual functions are public
friend std::ostream& operator>(std::istream&, Vector&);
protected: //needed by derived classes
Vector() { }
Vector(const Vector&) = default;
Vector(Vector&&) = default;
Vector& operator=(const Vector&) = default;
Vector& operator=(Vector&&) = default;
public:
static const double pi;
virtual double get_length() const = 0;
virtual Vector& normalise() = 0;
virtual explicit operator bool() const = 0;
virtual ~Vector() { } //needed if we dynamically allocate
private: //used for operator>
virtual std::ostream& print(std::ostream&) const = 0;
virtual std::istream& read(std::istream&) = 0;
};

std::ostream& operator>(std::istream&, Vector&);

class Vector2 : public Vector {
friend bool operator==(const Vector2&, const Vector2&);
friend bool operator!=(const Vector2&, const Vector2&);
friend Vector2 operator+(const Vector2&, const Vector2&);
friend

Solution

This is a problem made for templates and using inheritance here is a bad idea. Instead of trying to make this work with inheritance I would stongly consider reading about templates. Templates are really simple to implement and for this code all you really need is one line of code template before class Vector to get ridd of the Vector2,Vector3,... classes:

template
class Vector{
   private:
     double x[N]; // Components of a general N-dim vector
   ...

   // Example of how to write a general function. You can use N
   // as a normal integer within the class
   void normalize(){
      double norm = 0.0;
      for(int i = 0; i < N; i++){
        norm += x[i]*x[i];
      }
      norm = 1.0/sqrt(norm);
      for(int i = 0; i < N; i++){
        x[i] *= norm;
      }
   }

   ...
}


You would then create a 2D vector by simply writing Vector v;. This also gets ridd of all the code duplication you now have! As a bonus it will work for all N and you can also template over the type with little change to the code and get a vector that works with other types like float for free.

Some comments on your code:

As of now you have nothing useful in the base-class except for virtual function definitions and static const double pi so this class is not really neeed at all - it just adds unnessesary code. Also pi is not really part of a vector so it does not belong in the class. If you really need pi as a constant get it from the math library.

Instead of having the component separate as double x, y, z, ... I would use an array here double x[N]. If you do this then you can then replace the functions getX,getY,getZ with a single function

double getCoordinate(unsigned int i){
    if( i < N ) { 
       return x[i];
    } else {
       // Raise error, this is not a valid coordinate
       // ...
    }
}


Likewise you can replace setX,setY,setZ with setCoordinate(unsigned int i).

Code Snippets

template<unsigned int N>
class Vector{
   private:
     double x[N]; // Components of a general N-dim vector
   ...

   // Example of how to write a general function. You can use N
   // as a normal integer within the class
   void normalize(){
      double norm = 0.0;
      for(int i = 0; i < N; i++){
        norm += x[i]*x[i];
      }
      norm = 1.0/sqrt(norm);
      for(int i = 0; i < N; i++){
        x[i] *= norm;
      }
   }

   ...
}
double getCoordinate(unsigned int i){
    if( i < N ) { 
       return x[i];
    } else {
       // Raise error, this is not a valid coordinate
       // ...
    }
}

Context

StackExchange Code Review Q#108072, answer score: 6

Revisions (0)

No revisions yet.