Programming Workshop 2 (CSCI 1061U)
Faculty of Science, Ontario Tech University
Our goal is to create a vec2
class that can be used to
store the information of a 2-dimensional (2D) 0vector. As seen in the
figure below, each 2D vectors has two components: \(x\) and \(y\). We will use this class to illustrates
C++ classes in action.
class
keywordpublic
, protected
, and
private
this
pointer&
vec2.h
See the vec2.h
that defines the vector class.
#include <iostream>
class vec2 {
public:
double x;
double y;
public:
// Constructors
();
vec2(double c);
vec2(double x, double y);
vec2(const vec2& o); // Copy constructor
vec2
// Destructor
~vec2();
public:
double length();
// Assignment operator
& operator=(const vec2& o);
vec2};
vec2.cpp
The corresponding vec2.cpp
file is
#include "vec2.h"
#include "math.h"
using namespace std;
::vec2() : x(0.0), y(0.0) // This is called the initializer-list.
vec2// We can use it to initialize the member data.
{}
::vec2(double c)
vec2{
this->x = c;
this->y = c;
}
::vec2(double x, double y)
vec2{
this->x = x;
this->y = y;
}
::vec2(const vec2& o) // The copy constructor.
vec2// const keyword indicates that
// we are not allowed to modify the
// passed reference, which makes sense
// it is unwise to modify o when copying it.
{
= o.x;
x = o.y;
y }
::~vec2() // This is called when an instance is destroyed
vec2// 1. Goes out of scope
// 2. delete is called (in case of dynamic allocations)
{}
& vec2::operator=(const vec2& o) // The assignment operator.
vec2// const keyword indicates that
// we are not allowed to modify the
// passed reference, which makes sense
// it is unwise to modify o when copying it.
{
= o.x;
x = o.y;
y return *this; // this is a pointer that points to this instance of vec2.
// here, we are return a reference, so we need an object.
// we use the de-reference operator * to do so.
}
double vec2::length()
{
return sqrt(x*x + y*y);
}
main.cpp
main.cpp
file below uses this 2D vectors.
#include <iostream>
#include "vec2.h"
using namespace std;
int main()
{
;
vec2 a.x = 1.5;
a.y = 2.7;
a
(2.4, 54.4);
vec2 b//cout << "length of b = " << b.length() << endl;
<< "a = (" << a.x << "," << a.y << ")" << endl;
cout << "b = (" << b.x << "," << b.y << ")" << endl;
cout
* c = new vec2(9.9999);
vec2<< "c = (" << c->x << "," << c->y << ")" << endl;
cout delete c;
= a; // Using the assignemnt operator
b << "b = (" << b.x << "," << b.y << ")" << endl;
cout
return 0;
}
We can compile the above code as follows
$ g++ main.cpp vec2.cpp -o vec2
Continued from above
const
functions: indicate that this member function
doesn’t change the current instance.const
references: these references cannot be used
to modify an instance. these can only be passed to functions that expect
a const reference.friends
functions: non-member functions and
operators of class that can access protected members and methods of that
class.>>
) operator: used to send
contents to an ostream, such as cout, a file, etc.<<
) operator: used to read contents
from an istream, such as cin, a file, etc.Consider the following vec2.h
file that showcases the
use of const
and friend
functions.
It also provides a recipe for writing insertion <<
and extraction >>
operators.
#include <iostream>
class vec2 {
protected:
double x;
double y;
public:
();
vec2(double c);
vec2(double x, double y);
vec2(const vec2& o); // Copy constructor
vec2~vec2(); // Destructor
public:
double length2() const; // A member const function
// to compute the squared length
// of this function. By declaring
// this function const, we
// promise that this function
// will not modify "this" instance, i.e.,
// members x and y will remain unchanged.
// this allows the following to work
//
// vec2 v(1,2);
// const vec2& const_v_ref = v;
// cout << "Squred length = " << const_v_ref.length2() << endl;
//
// Note that if this function was not
// declared const, the following statement
// will give a compile-time error:
//
// const_v_ref.length2()
friend double length2(const vec2& v); // A friend function, which is not
// not a member of vec2, to compute
// the squred length of this vector.
// Since this function is not a member,
// we need to pass a vec2 as argument.
// Here we pass a const references to
// a vec2. This is the recommended
// approach to pass objects due to the following
// advantages:
// 1. We are only passing a reference to
// the object, avoiding a copy.
// 2. Since we don't expect a vec2 to
// change because its squared length
// is computed, we pass a const reference.
// Note that we also decrare this function
// a friend. That allows that vec2 instance
// within this function can access the protected
// members of vec2.
const vec2& operator=(const vec2& o) { // Assignment operator
= o.x;
x = o.y;
y return *this;
}
// vec2 a, b;
// cout << a << ' ' << b << endl;
friend std::ostream& operator<<(std::ostream& stream, const vec2& o) { // Insertor operator
// Use to insert data to
// ostream objects
<< o.x << ' ' << o.y;
stream return stream;
}
// vec2 a
// cin >> a;
friend std::istream& operator>>(std::istream& stream, vec2& o) { // extractor operator
// Use to extract data from
// istream objects
>> o.x;
stream >> o.y;
stream return stream;
}
}
The corresponding cpp file vec2.cpp
is
#include "vec2.h"
#include "math.h"
using namespace std;
::vec2() : x(0.0), y(0.0)
vec2{
}
::vec2(double c)
vec2{
= c;
x = c;
y }
::vec2(double x, double y)
vec2{
this->x = x; // Using this pointer to differentiate
this->y = y; // between members x and y and
// function arguments x and y.
}
::vec2(const vec2& o)
vec2{
= o.x;
x = o.y;
y }
::~vec2()
vec2{}
double vec2::length2() const
{
return x*x + y*y;
}
double length2(const vec2& v)
{
return v.x*v.x + v.y*v.y;
}
And the main.cpp
file that you can use to experiment
with these files is
#include <iostream>
#include "vec2.h"
using namespace std;
int main()
{
(2,4);
vec2 a<< "a = " << a << endl;
cout << "length of a = " << a.length2() << endl;
cout << "length of a = " << length2(a) << endl;
cout
const vec2& b = a;
<< "length of b = " << b.length2() << endl;
cout
;
vec2 c= b;
c << "length of c = " << c.length2() << endl;
cout
;
vec2 d<< "d = " << d << endl;
cout << "Enter d: ";
cout >> d;
cin << "d = " << d << endl;
cout
return 0;
}
You can compile this program as follows:
$ g++ vec2.cpp main.cpp -o v