Each exercise this quarter is rated on a integer scale of 1 – 5, inclusive, with 1 being the "least time-consuming" and 5 being the "most time-consuming".
This difficulty scale is meant as a rough guide for you in predicting the amount of time to set aside for each exercise as you balance the work required for 333 with your other obligations. However, it is necessarily imperfect as everyone's set of circumstances and experiences with the exercises differ. If your experience with an exercise does not align with its rating, that is not a reflection of you or your abilities.
Work through this exercise in the following order:
ex5.cc and answer the warm-up
questions in questions.txt (in the starter). The
questions walk you through discovering which constructors,
methods, and operators your class must support, what data members
it needs, and what signatures those operations require.Vector.h and
Vector.cc.You will not be graded on the correctness of your answers. They are an opportunity for you to reflect. You may freely discuss the warm-up questions with other students.
Submit
your completed questions.txt along with your code.
In this exercise you will write your first C++ class,
Vector, a 3-D vector. Writing it brings up most of the
design decisions that go into properly encapsulating a class:
const-correctness, reference vs. non-reference
parameters and return values, constructors, destructors, operator
overloading, and the choice between member, non-member, and
friend functions.
Vector's three components live in a
heap-allocated array, so you must manage dynamic
memory (the Rule of Three).friends.
The array should be allocated when a Vector is created
and freed when it is destroyed. The Vector class and
all of its associated functions must live in a namespace named
vector333.
The provided ex5.cc shows exactly how your
Vector is used, and its expected output (below) shows
how each operation should behave. Your first warm-up question is to
read ex5.cc and work out the full set of constructors,
operators, and other functions your class needs, along with what
each one should do.
Note that any operation that returns a
Vector must return an actual Vector value,
not a pointer to one allocated elsewhere.
We provide ex5.cc, a main that exercises
your Vector class, so you do not need to write
your own tests. Because the class has no getters, testing is done by
printing output rather than by checking return values with
status codes (as you did in earlier exercises). Build with the
provided Makefile and confirm that your implementation
produces exactly the output below:
$ make $ ./ex5 default Vector, should be (0,0,0): (0,0,0) Vector with initial values, should be (1,2,3): (1,2,3) Vector from copy constructor, should be (1,2,3): (1,2,3) Vector assignment, should have three copies of (3.1,-2.5,2.7): (3.1,-2.5,2.7) (3.1,-2.5,2.7) (3.1,-2.5,2.7) Updating assignment, should have two copies of (4.1,-0.5,5.7): (4.1,-0.5,5.7) = (4.1,-0.5,5.7) Updating assignment, should have two copies of (3.1,-2.5,2.7): (3.1,-2.5,2.7) = (3.1,-2.5,2.7) Arithmetic: (3.1,-2.5,2.7) + (1,2,3) = (4.1,-0.5,5.7) (3.1,-2.5,2.7) - (1,2,3) = (2.1,-4.5,-0.3) Dot product: (a,b,c) * (x,y,z) = (ax+by+cz) (1,2,3) * (1,2,3) = 14 Scalar product: (a,b,c) * k = (ak,bk,ck) (3.1,-2.5,2.7) * 2 = (6.2,-5,5.4) 2 * (3.1,-2.5,2.7) = (6.2,-5,5.4)
Vector.h declares the Vector class and
its associated functions. You write this.Vector.cc implements the Vector class.
You write this.ex5.cc is the test driver. Provided.Makefile builds the ex5 executable.
Provided.
The starter Vector.h and Vector.cc
contain only the copyright header for you to fill in. See
Compilation for how to build.
Normally, a class's private fields can't be read by
functions outside the class. C++ lets you get around this by
declaring a function as a friend, which gives that one
function permission to read the private members.
A friend is an ordinary non-member function, not a
method. You need friends here because a few operations have to read
a Vector's components but can't be members: the dot
product, scalar multiplication, and stream output.
To write one:
friend keyword.friend keyword and no
ClassName:: qualifier.For example:
// Point.h
class Point {
public:
Point(int x, int y) : x_(x), y_(y) { }
// Grant this non-member function access to Point's private members.
friend std::ostream& operator<<(std::ostream& out, const Point& p);
private:
int x_, y_;
};
// Point.cc -- defined as a normal non-member function (no "friend", no "Point::")
std::ostream& operator<<(std::ostream& out, const Point& p) {
out << "(" << p.x_ << "," << p.y_ << ")"; // allowed to read private x_, y_
return out;
}
Only grant friend access to non-member functions that
truly need it. A non-member function that can do its job using
other public operations should not be a
friend. For instance, operator+ can be
written using the public operator+=, so it needs no
special access and should not be a friend.
You could avoid friends entirely by adding getters, but that would break the encapsulation we want, which is why this exercise leaves them out.
We provide a Makefile for this exercise, so you do
not need to write one yourself. To build the
ex5 executable, just run:
$ make
You can remove the generated executable and object files with:
$ make clean
Under the hood, this compiles your code the same way as the command
below (each .cc source file #includes
Vector.h):
$ g++ -Wall -g -std=c++17 -o ex5 ex5.cc Vector.cc
We recommend referring to the examples from lecture while
implementing this exercise. We also suggest you implement operators
and test them one at a time. After everything has been implemented,
make a style pass and double-check whether each function should be
a member, a non-member, or a non-member friend
function.
Make sure you use new and delete, as
opposed to their C counterparts. Follow the best practices for
handling dynamically allocated memory in objects; in particular,
investigate all of the functions related to the Rule of Three.
Make sure your main has no memory leaks, even for
non-typical exits (e.g., handling edge cases or test
failures). We will be using valgrind
(valgrind --leak-check=full ./ex5) to check for memory
issues.
Our autograder compiles its own tests against your
Vector.h, so your class name (Vector) and
the namespace (vector333) must match this
specification exactly, including capitalization. Every
operation must also be callable exactly the way ex5.cc
uses it.
Deciding whether each function is a member, a plain non-member, or
a non-member friend is one of the subtler parts of C++
class design. Some operations can only be one of these; others
could go either way but have a stylistic preference. Grant
friend access only to non-member functions that
genuinely need to read the class's private members, and
review the related lecture material carefully.
Functions, parameters, and variables should be labeled with
const appropriately throughout your program. Refer to
the lecture material for best practices.
Submit your work by creating an ex5-submit tag in your exercise repo before the assignment deadline.
For full credit, your code must:
attu, or CSE home VM) using the
command in the Compilation
section.g++ and valgrind)..cc and .h files with your name(s)
and CSE or UW email address(es).cpplint.py).