# Creating a 2D Vector Using C++

• ChrisVer
In summary, the Vec2D class has a fX and fY field, a SetX and SetY methods, and a print method. The class also has addVector and scalarProduct methods. The Vec2D class can be used to create a vector that is the sum of two other vectors. When the Vec2D class is used with the const keyword, the compiler errors out.f

#### ChrisVer

Gold Member
I have the following class Vec2D:
Code:
#ifndef Vec2D_H
#define Vec2D_H

class Vec2D
{
private:
double fX;
double fY;
public:
Vec2D();
Vec2D(double x=0, double y=0);
~Vec2D() {};
double const X();
double const Y();
void SetX(double a);
void SetY(double b);
void print();
double scalarProduct(const Vec2D& v2) const;
};

#endif

Code:
#include "Vec2D.h"
#include <iostream>

Vec2D::Vec2D(){
fX= 0.;
fY= 0.;
}

Vec2D::Vec2D(double x, double y)
{
fX=x;
fY=y;
}

void Vec2D::SetY(double a){
fY=a;
}
void Vec2D::SetX(double b){
fX=b;
}
double const Vec2D::X(){
return fX;
}
double const Vec2D::Y(){
return fY;
}

void Vec2D::print(){
std::cout<<"("<<fX<<", "<<fY<<")";
}

{
double v2_x,v2_y,v1_x,v1_y;
v2_x=v2.fX;
v2_y=v2.fY;
v1_x=fX;
v1_y=fY;
double x_new, y_new;
x_new= v1_x +v2_x;
y_new= v1_y +v2_y;
return Vec2D(x_new, y_new);
}

double Vec2D::scalarProduct(const Vec2D& v2) const
{
double v2_x, v2_y, v1_x, v1_y,prod;
v2_x= v2.fX;
v2_y= v2.fY;
v1_x=fX;
v1_y=fY;
prod=(v2_x*v1_x)+(v2_y*v1_y);
return prod;
}

My problem is when I am trying to do something with the Vec2D::scalarProduct() and Vec2D::addVector() methods I am getting an error of the following type:
"[linker error] undefined reference to Vec2D::scalarProduct(Vec2D&)"
And this error started appearing when I tried to implement the keyword "const" in my arguments of those two methods (const Vec2D) and at the end of the methods' names METHOD(ARGS) const{ ... }.
Without that keyword my code runs smoothly...any help? Thanks.
ooh yes my main code also is:
Code:
#include <iostream>
#include "Vec2D.h"
int main(){
Vec2D a= Vec2D(1.,2.);
Vec2D b= Vec2D(3.,4.);
Vec2D c= Vec2D(2.,-1.);
sum.print();
double p1= a.scalarProduct(b);
double p2= a.scalarProduct(c);
double p3= c.scalarProduct(b);
std::cout<<p1<<"\t"<<p2<<"\t"<<p3<<std::endl;
system("pause");
return 0;
}

Why do you need the 'const' keyword in there... from as much as I can tell it doesn't look like it's a constant at all... Why would you need a function that returns a constant?

For example. const Vector2d::X returns fX, which isn't a constant, so it can't be evaluated at compile time, which is probably what the compiler is complaining about

What is not constant?
the Vec2D::X() returns fX, but the return value is a constant... fX doesn't have to be... I don't think the compiler raises any error (at least I tried it now) with the assignment of non-constant objects to constants...
It raises an error if you try to change the const ones.

What I don't understand is why the code results to such an error after I inserted the const keywords on the addVector and scalarProduct methods.. From looking around for that error message I was left with the impression that there is a problem for the compiler when it tries to connect/match my cpp with my header file (and so the linker)... But in both those files I am using the same naming etc.
And let me elaborate with an example?
I have a vector A=(1,2)
and a vector B= (1,5)
I want the addition C=A+B = (2,7)
Now I can take the object A and using the method addVector add to its elements the vector's B ones? I can make sure that my B is not changed (read-only object) by passing it as a constant reference.

Last edited:
Can you try omitting the const keyword from the cpp file and leaving it in the header file?

I'm no expert at this, but I've done this enough to know the frustration you can get from compiler errors!.. Maybe someone else will chime in.

Can you try omitting the const keyword from the cpp file and leaving it in the header file?

Well I just did to make sure of my fear that it wouldn't work; omitting it of course results in not finding the method in the header file.

I just understood that constants had to be evaluable at compile time, and an instance of your class will always return the same value, but each different instance will have a different return value, meaning it's not constant...
I'm going to fiddle a little with it myself :)

ChrisVer said:
C:
Vec2D Vec2D::addVector(const Vec2D& v2) const
{
double v2_x,v2_y,v1_x,v1_y;
v2_x=v2.fX;
v2_y=v2.fY;
v1_x=fX;
v1_y=fY;
double x_new, y_new;
x_new= v1_x +v2_x;
y_new= v1_y +v2_y;
return Vec2D(x_new, y_new);
}

double Vec2D::scalarProduct(const Vec2D& v2) const
{
double v2_x, v2_y, v1_x, v1_y,prod;
v2_x= v2.fX;
v2_y= v2.fY;
v1_x=fX;
v1_y=fY;
prod=(v2_x*v1_x)+(v2_y*v1_y);
return prod;
}
I could be wrong, but I think you really should remove the const attributes from your function return values, as also noted by Rx7man.

In addition, your definitions for the two functions I copied above are overly complicated. You should not have the declarations you show in the first line of each of these methods. In both methods the parameter is the vector that will be used to add to the vector on which the method is called, or to calculate the scalar product of the vector on which the method is called. One important fact that you're ignoring is that for methods of a class, the implied first argument is the this pointer, where this points to the instance of the class.

In the first method (addVector), this.fx and this.fy are the coordinates of the vector on which the method is called. The parameter, v2, has its own coordinates; namely, v2.fx and v2.fy.

C:
Vec2D Vec2D::addVector(const Vec2D& v2)
{
Vec2D v_new(this->x, this->y);
return v_new;
}

For this to work, though, you need a copy constructor, and to be able to use this method, you need to overload the assignment operator. Note that I have renamed your private class members from fX and fY to x and y.

The copy constructor looks like this:
C:
Vec2D::Vec2D(const Vec2D& v)
{
this->x = v.x;
this->y = v.y;
}

My overloaded assignment operator looks like this:
C:
Vec2D Vec2D::operator= (const Vec2D & v)
{
this->x = v.x;
this->y = v.y;
return *this;
}

Last edited:
ChrisVer
In addition to what I said above, my implementation of the scalarProduct() method has one line of code. Again, methods on classes always have an implied first argument, the this pointer, a pointer to (the address of) the object on which the method is called. You aren't using this in your method implementations.

In addition to what I said above, my implementation of the scalarProduct() method has one line of code. Again, methods on classes always have an implied first argument, the this pointer, a pointer to (the address of) the object on which the method is called. You aren't using this in your method implementations.

Is the this keyword the C++ analogue of self in python? Although python doesn't have pointers for the ->.

Yes - or as close as you can get. But you don't have to declare it in the method definition. It's just there automagically.

Is the this keyword the C++ analogue of self in python? Although python doesn't have pointers for the ->.
They're similar, with self in Python representing the object, and this being a pointer to the object.

I don't know how it works in C++, but in VB, typically when you call the default constructor, you pass default default values to the non-default constructor...

so it would look something like this, and would reduce the locations of code to debug

Code:
Vec2D::Vec2D(){
Vec2D(0,0);           //call the non default constructor with default values (syntax may not be right)
}

Vec2D::Vec2D(double x, double y)
{
fX=x;   //do the initialization for both cases here in the non-default contructor.. and you may need "this" here as well
fY=y;
}

I don't know how it works in C++, but in VB, typically when you call the default constructor, you pass default default values to the non-default constructor...

so it would look something like this, and would reduce the locations of code to debug

Code:
Vec2D::Vec2D(){
Vec2D(0,0);           //call the non default constructor with default values (syntax may not be right)
}

Vec2D::Vec2D(double x, double y)
{
fX=x;   //do the initialization for both cases here in the non-default contructor.. and you may need "this" here as well
fY=y;
}
In the code that @ChrisVer posted at the start of this thread, the header file contains these declarations:
C:
Vec2D();
Vec2D(double x=0, double y=0);
The first constructor can be removed; the second constructor passes default values of 0 and 0 if a Vec2D object is created with no initializers. If a Vec2D object is created with initializer values, those values are used to set the x and y members.

Rx7man