Classes in C++

Programming Workshop 2 (CSCI 1061U)

Faculty of Science, UOIT

http://vclab.science.uoit.ca

A Working Example

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. 2-dimenstional vectors

Part 1: The Basics

Topics

• The class keyword
• Access modifiers: public, protected, and private
• Member variables and member functions
• Constructor and destructor
• Initializer list
• this pointer
• Reference &

vec2.h

See the vec2.h that defines the vector class.

#include <iostream>

class vec2 {
public:
double x;
double y;

public:

// Constructors
vec2();
vec2(double c);
vec2(double x, double y);
vec2(const vec2& o); // Copy constructor

// Destructor
~vec2();

public:
double length();

// Assignment operator
vec2& operator=(const vec2& o);
};

vec2.cpp

The corresponding vec2.cpp file is

#include "vec2.h"
#include "math.h"

using namespace std;

vec2::vec2() : x(0.0), y(0.0) // This is called the initializer-list.
// We can use it to initialize the member data.
{}

vec2::vec2(double c)
{
this->x = c;
this->y = c;
}

vec2::vec2(double x, double y)
{
this->x = x;
this->y = y;
}

vec2::vec2(const vec2& o) // The copy constructor.
// 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.
{
x = o.x;
y = o.y;
}

vec2::~vec2() // This is called when an instance is destroyed
// 1. Goes out of scope
// 2. delete is called (in case of dynamic allocations)
{}

vec2& vec2::operator=(const vec2& o) // The assignment operator.
// 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.
{
x = o.x;
y = o.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;
a.x = 1.5;
a.y = 2.7;

vec2 b(2.4, 54.4);
//cout << "length of b = " << b.length() << endl;

cout << "a = (" << a.x << "," << a.y << ")" << endl;
cout << "b = (" << b.x << "," << b.y << ")" << endl;

vec2* c = new vec2(9.9999);
cout << "c = (" << c->x << "," << c->y << ")" << endl;
delete c;

b = a; // Using the assignemnt operator
cout << "b = (" << b.x << "," << b.y << ")" << endl;

return 0;
}

Compilation

We can compile the above code as follows

$g++ main.cpp vec2.cpp -o vec2 Part 2: More Than Just Basics Continued from above Topics • 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. • extractor (>>) operator: used to send contents to an ostream, such as cout, a file, etc. • insertor (<<) operator: used to read contents from an istream, such as cin, a file, etc. Implementation 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. vec2.h #include <iostream> class vec2 { protected: double x; double y; public: vec2(); vec2(double c); vec2(double x, double y); vec2(const vec2& o); // Copy constructor ~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 x = o.x; y = o.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 stream << o.x << ' ' << o.y; return stream; } // vec2 a // cin >> a; friend std::istream& operator>>(std::istream& stream, vec2& o) { // extractor operator // Use to extract data from // istream objects stream >> o.x; stream >> o.y; return stream; } } vec2.cpp The corresponding cpp file vec2.cpp is #include "vec2.h" #include "math.h" using namespace std; vec2::vec2() : x(0.0), y(0.0) { } vec2::vec2(double c) { x = c; y = c; } vec2::vec2(double x, double y) { this->x = x; // Using this pointer to differentiate this->y = y; // between members x and y and // function arguments x and y. } vec2::vec2(const vec2& o) { x = o.x; y = o.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; } main.cpp 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() { vec2 a(2,4); cout << "a = " << a << endl; cout << "length of a = " << a.length2() << endl; cout << "length of a = " << length2(a) << endl; const vec2& b = a; cout << "length of b = " << b.length2() << endl; vec2 c; c = b; cout << "length of c = " << c.length2() << endl; vec2 d; cout << "d = " << d << endl; cout << "Enter d: "; cin >> d; cout << "d = " << d << endl; return 0; } Compilation You can compile this program as follows: $ g++ vec2.cpp main.cpp -o v
• Absolute C++, 6th Edition, W. Savitch.