CS32, Fall 2017

Lab02:
Overloading operators in C++


Goals for this lab

By the time you have completed this lab and its homework, you should

Step by Step Instructions

Step 1: Get set up, including copying files to your lab directory

Partner up (and remember to switch roles after awhile). If your regular partner is more than 5 minutes late, ask the TA to pair you with someone else for this week. This lab's first pilot should log in. You will (both) work in this account for the rest of the lab.

Create a ~/cs32/lab02 directory, make it your current directory, and get copies of five files from the cs32 class account:

mkdir ~/cs32/lab02
cd ~/cs32/lab02
cp ~cs32/labs/lab02/* .

Step 2: Start building a Vec3 class

You are provided with a simple Makefile, main.cpp, and incomplete versions of vec.h and vec.cpp. There is also a file called main2.cpp to be used in the "After lab-work" section.

In this lab, you will need to add all the functionality that main.cpp expects from the Vec3 class. This requires both declaring new functions in vec.h and writing the corresponding implementation in vec.cpp. After making each class enhancement, you will uncomment lines in main.cpp to test it. The optional lab tasks follow the same procedures.

Right now: use an editor to type your name(s) and today's date in the comments at the top of two of these files: both vec.h and vec.cpp.

Study what's done already

The class already has a no-argument constructor, a constructor that takes three double values, and a copy constructor - all of which are implemented in vec.cpp too. Do not change the way they are defined or implemented.

Especially note the way the copy constructor is implemented: its purpose is to insure that your code properly defines certain functions to accept parameters that are passed by-reference instead of by-value. Any attempt to pass a Vec3 object by-value will invoke this copy constructor - and that should never happen.

Getters and setters for x, y and z are also defined and implemented already.

Make sure your copies are working:

bash-4.3$ make
g++ -Wall main.cpp vec.cpp -o main
bash-4.3$ ./main
From default constructor: 0 0 0
From 3-param constructor: 5.5 6.6 7.7

For each of the remaining steps, you must (a) add definitions to vec.h, (b) implement these enhancements in vec.cpp, and (c) uncomment code in main.cpp that tests it. Then compile with make, and execute to verify results are correct before continuing to the next step.

Step 3: Overload << for cout (and streams of its kind)

The goal is to make the << operator work to output the values of a Vec3 object's x, y and z data to an ostream object like cout like so:

(x, y, z)

Of course, x, y, and z should be replaced by their double values. For example, given the initial values of the vector created with the 3-param constructor, vec_1, the following statement ...

cout << vec_1 << endl;

... should print this:

(5.5, 6.6, 7.7)

This function should be declared in vec.h as a non-member function that is a "friend" of class Vec3. The function should take two parameters: an ostream& and a const Vec3&. It should return the ostream as a reference variable. And the function's name must be operator<<.

Define the function now in vec.h, and implement it in vec.cpp. Then uncomment the first two lines that test it in main.cpp (20-21 in the original), compile and execute. Results should match the following exactly:

From default constructor: 0 0 0
From 3-param constructor: 5.5 6.6 7.7
From default constructor using <<: (0, 0, 0)
From 3-param constructor using <<: (5.5, 6.6, 7.7)

Step 4: Overload >> for cin (and other istreams)

Now define operator>>: to retrieve new data for a Vec3 object from an istream& like cin. Declare it in vec.h (it looks very much like the operator<< you created in the last step), and implement it in vec.cpp. Notice that main.cpp already prompts the user to enter 3 double values, so your function should just read the data and not prompt the user again. You should return the istream object as a reference variable. Why?

Uncomment the lines in main.cpp that test this feature (25-27 in the original), compile again, and execute. You should be able to enter 3 doubles, and verify they are printed in the last line of output. For convenience, you can run your program via the following command to avoid having to retype the numbers each time:

echo "1.1 2.2 3.3" | ./main

The output looks a bit funny that way, but it's worth it if you must test many times.

Step 5: Overload + for adding two Vec3 instances

Now you will need to overload "+" so that you can add two Vec3 instances, to create a third Vec3 instance. Think about what the parameters should be and what the return value should be. Vec3 objects are added by adding their individual components together. For example, `Vec3(1, 2, 3) + Vec3(4, 5, 6)` should produce `Vec3(5, 7, 9)`.

And like the others, this function should be a non-member function. Why? Because it involves more than one object again, in fact three of them this time. Make it a friend of the class to simplify your coding.

Test this new functionality as before.

Step 6: Overload * to multiply a Vec3 instance by a double value

This function should create a Vec3 object that contains multiples of all the components of another Vec3 object. Specifically, each component of the Vec3 should be multiplied by the value of the double. For example, `Vec3(1, 2, 3) * 4` should produce `Vec3(4, 8, 12)`.

Again there is more than one object being handled by the function. What is the implication of that fact? Right: it means this function should be a non-member function too. (Don't worry: the "After lab work" includes a member operator, and the homework includes more.) Make this one a friend too.

Get it working and test it after uncommenting the last two statements in main.cpp. By now you should be able to successfully run the complete `main.cpp` program. Given the command listed in step 3, `main` should produce the following output:

bash-4.3$ echo "1.1 2.2 3.3" | ./main
From default constructor: 0 0 0
From 3-param constructor: 5.5 6.6 7.7
From default constructor using <<: (0, 0, 0)
From 3-param constructor using <<: (5.5, 6.6, 7.7)
Input three doubles: Updated using >> overloading: (1.1, 2.2, 3.3)
The previous two added together: (6.6, 8.8, 11)
More addition: (13.2, 17.6, 22)
Simple multiplication: (8.8, 17.6, 26.4)
More multiplication: (6.6, 13.2, 19.8)

Step 7: Submit vec.h and vec.cpp

If you don't already have an account on the submit system, make one now at https://submit.cs.ucsb.edu/form/user.

The Create New Account form will insist that you sign up using your umail address, and we insist you enter the name listed on the roster (not a nickname that you go by).

Once you've created your account, login with the email and password you used to register. At the login page, follow the Join Class link, and then click the button labelled "Join CS32_f17" to join our class for this quarter.

Click the "Make Submission" button next to Lab02 (at https://submit.cs.ucsb.edu/), or use the following command from a CS terminal:

~submit/submit -p 855 vec.cpp vec.h
Wait for the results of both tests.

If you are working with a partner, be sure that both partners' names are in a comment at the top of the source code file, and be sure to properly form a group for this project in the submit.cs system.

Do beware that all parts must be working to earn any points at all from the submit.cs tests.


Evaluation and Grading

Each pair of students must accomplish the following to earn full credit for this lab:


After lab-work is done

All students should do the following tasks, whether or not you have time to do them during the lab session. Do the work on your own time if necessary. The concepts you learn by doing so may be tested as part of an upcoming exam.

Add enhancements to the vec3 class

Each of the following items add functionality to the Vec3 class, meaning they require additions to both vech.h and vec.cpp, like the required steps above. Use the second testing program, main2.cpp. As before, uncomment the appropriate parts when you are ready to test them.

Add a couple more non-member, binary operator functions

First overload operator* again, this time so it will allow the double value to be on the left side of the expression, as in `4 * vec_0` instead of the reverse. (You knew the current version won't work that way now, right?) This function can be easily implemented by using the existing operator* function. Here are the expected results from testing this part with ./main2:

bash-4.3$ echo "1.1 2.2 3.3" | ./main2
Input three doubles: Input vector: (1.1, 2.2, 3.3)
Constant vector: (5.5, 6.6, 7.7)
Simple multiplication: (8.8, 17.6, 26.4)
More multiplication: (6.6, 13.2, 19.8)

Now add a binary operator- function to subtract the right-side argument from the left-side one. You can implement it by using the existing operator+ and operator* functions: a-b is the same as a+(-1*b). Results should match the following (continued from ./main2 run above):

Input vector - const vector: (-4.4, -4.4, -4.4)
More subtraction: (-11, -13.2, -15.4)

Add a member, unary operator*= function

When invoked, the Vec3 object must appear on the left side of the expression - the idea is to multiply the x, y and z data of this object all by the same double value. This double value will be the function's only argument, and so it is necessary to make this function a member of the class - that way, the pointer named this will be passed to it automatically, giving the function immediate access to x, y and z. The function should return a Vec3& - the same object upon which it was called. Do you remember the name of the calling object? Well if this is the pointer, then what is the object? The ./main2 results for this part are as follows:

Input vector after *= 2: (2.2, 4.4, 6.6)
Last result *=.5: (1.1, 2.2, 3.3)

Add the following features too:

Here are the continued results from the ./main2 runs above, after all parts are completed:

Input vec += constant vec: (6.6, 8.8, 11)
     Verify still changed: (6.6, 8.8, 11)
++(Last vec) : (7.6, 9.8, 12)
  Verify same: (7.6, 9.8, 12)
(Last vec)++ : (7.6, 9.8, 12)
  Verify diff: (8.6, 10.8, 13)
Constant's data: 5.5 6.6 7.7
Final vec: (77.77, 77.77, 77.77)

Prepared by Michael Costanzo, heavily based on a lab by Bryce Boe (summer 2012 CS 32 instructor).