Point.h

#ifndef POINT_H_
#define POINT_H_

// Class that represents a two-dimesional integral coordinate plane
class Point {
 public:
  Point(int x, int y);  // constructor
  int get_x() const { return x_; }  // inline member function
  int get_y() const { return y_; }  // inline member function
  double Distance(const Point &p) const;  // member function
  void SetLocation(int x, int y);  // member function

 private:
  int x_;  // data member
  int y_;  // data member
};  // class Point

#endif  // POINT_H_

Point.cc

#include "Point.h"

#include <cmath>  // sqrt

Point::Point(const int x, const int y) {
  // BAD STYLE: shouldn't mix-and-match direct field access (x_)
  // and access via this (this->y_).
  x_ = x;
  this->y_ = y;  // this-> is optional, unless names conflict
}

double Point::Distance(const Point& p) const {
  // We can access p's x_ and y_ variables either through the
  // get_x(), get_y() accessor functions, or the x_, y_ private
  // member variables directly, since we're in a member function of
  // the same class (BAD STYLE to mix-and-match, though).
  double distance = (x_ - p.get_x()) * (x_ - p.get_x());
  distance += (y_ - p.y_) * (y_ - p.y_);
  return sqrt(distance);
}

void Point::SetLocation(const int x, const int y) {
  x_ = x;
  y_ = y;
}

Point_2011.h

#ifndef POINT_2011_H_
#define POINT_2011_H_

class Point {
 public:
  Point(int x, int y);  // constructor

  // disable copy constructor and assignment operator by specifying
  // them as deleted functions (new in C++ 2011)
  Point(const Point& copyme) = delete;
  Point& operator=(const Point& rhs) = delete;

  int get_x() const { return x_; }  // inline member function
  int get_y() const { return y_; }  // inline member function

  void Clone(const Point& copy_from_me);    // update self
  double Distance(const Point& p) const;
  void SetLocation(int x, int y);

 private:
  int x_;  // data member
  int y_;  // data member
};  // class Point

#endif  // POINT_2011_H_

Point_2011.cc

#include "Point_2011.h"

#include <cmath>
#include <iostream>


Point::Point(const int x, const int y) : x_(x), y_(y) {
  std::cout << "Calling Point constructor" << std::endl;
}

void Point::Clone(const Point& copy_from_me) {
  x_ = copy_from_me.x_;
  y_ = copy_from_me.y_;
}

double Point::Distance(const Point& p) const {
  double distance = (x_ - p.x_) * (x_ - p.x_);
  distance += (y_ - p.y_) * (y_ - p.y_);
  return sqrt(distance);
}

void Point::SetLocation(const int x, const int y) {
  x_ = x;
  y_ = y;
}

sanepoint_2011.cc

#include <cstdlib>

#include "Point_2011.h"

int main(int argc, char **argv) {
  Point x(1, 2);
  Point y(3, 4);

  x.Clone(y);

  // Point z(x);  // compiler error, copy constructor is disabled.
  // x = y;       // compiler error, assignment operator is disabled.

  return EXIT_SUCCESS;
}

Complex.h

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

namespace complex {

class Complex {
  // Style tip: always put your public members before private members.
 public:
  Complex(double real, double imag);  // Constructor
  Complex(double real);               // overloaded Constructor
  Complex(const Complex& copyme);     // Copy constructor
  ~Complex();                         // Destructor

  // Accessors / mutators, defined inline.
  double real() const { return real_; }
  double imag() const { return imag_; }
  void set_real(const double real) { real_ = real; }
  void set_imag(const double imag) { imag_ = imag; }

  // Override the "-", "=", "+=", and "-=" operators.
  // Note that "-", like "+", could have been a non-member
  // function.  That would generally be better style since it can reduce
  // the amount of code with access to private instance data, and allows
  // "-" to treat its operators symmetrically, but we made it a member
  // function here as an example of what is possible.
  // "=", "+=", and "-=" normally should be member functions since
  // they do mutate the object's state instead of producing a new
  // object as a result.
  Complex operator-(const Complex& a) const;
  Complex& operator=(const Complex& a);
  Complex& operator+=(const Complex& a);
  Complex& operator-=(const Complex& a);

  // Overload ">>" for istream.  Note that this is a global
  // function, not a member function of class Complex.  It could
  // have been implemented as an ordinary, non-friend function
  // using the set_real() and set_imag() member functions and that
  // would generally be better style since it reduces the code that
  // has access to private data.  See "<<" for an example of a
  // non-friend stream i/o function.
  friend std::istream& operator>>(std::istream& in, Complex& a);

 private:
  double real_, imag_;  // Member variables.
};  // class Complex

// additional overloaded operators (not member or friend functions)
// (see above notes above about "-" and "<<", which should usually
// be done this way also when possible)

Complex operator+(const Complex& a, const Complex& b);

std::ostream& operator<<(std::ostream& out, const Complex& a);

}  // namespace complex

#endif  // COMPLEX_H_

Complex.cc

#include "Complex.h"

#include <iostream>
#include <sstream>
#include <string>


// This sample implementation prints diagnostic messages that
// would not be included in a production class, but are helpful
// for observing how the class works.

namespace complex {

Complex::Complex(const double real, const double imag) {
  std::cout << "constructor(" << real << "," << imag << ")";
  std::cout << ", the constructed object is at " << this << std::endl;
  this->real_ = real;
  this->imag_ = imag;
}

Complex::Complex(const double real) {
  std::cout << "constructor(" << real << ")";
  std::cout << ", the constructed object is at " << this << std::endl;
  this->real_ = real;
  this->imag_ = 0.0;
}

Complex::Complex(const Complex& copyme) {
  std::cout << "copy constructor(copy " << &copyme << ")";
  std::cout << ", the constructed object is at " << this << std::endl;
  this->real_ = copyme.real_;
  this->imag_ = copyme.imag_;
}

Complex::~Complex() {
  std::cout << "destructor of object at " << this << std::endl;
}

Complex Complex::operator-(const Complex& a) const {
  Complex tmp(0, 0);
  std::cout << "-: subtracting " << this << " - " << &a;
  std::cout << ", tmp is at " << &tmp << std::endl;
  tmp.real_ = this->real_ - a.real_;
  tmp.imag_ = this->imag_ - a.imag_;
  return tmp;
}

Complex& Complex::operator=(const Complex& a) {
  std::cout << "=operator: " << this << " = " << &a << std::endl;
  if (this != &a) {
    this->real_ = a.real_;
    this->imag_ = a.imag_;
  }
  return *this;
}

Complex& Complex::operator+=(const Complex& a) {
  std::cout << "+=operator: " << this << " += " << &a << std::endl;
  this->real_ += a.real_;
  this->imag_ += a.imag_;
  return *this;
}

Complex& Complex::operator-=(const Complex& a) {
  std::cout << "-=operator: " << this << " -= " << &a << std::endl;
  this->real_ -= a.real_;
  this->imag_ -= a.imag_;
  return *this;
}

// additional non-member overloaded operators in complex namespace

Complex operator+(const Complex& a, const Complex& b) {
  Complex tmp = a;
  std::cout << "+: adding " << &a << " + " << &b;
  std::cout << ", tmp is at " << &tmp << std::endl;
  tmp += b;
  return tmp;
}

std::ostream& operator<<(std::ostream& out, const Complex& a) {
  std::cout << "<<operator: from " << &a << std::endl;
  out << "(" << a.real() << " + " << a.imag() << "i)";
  return out;
}

std::istream& operator>>(std::istream& in, Complex& a) {
  std::cout << ">>operator: to " << &a << std::endl;

  double realtmp, imagtmp;
  // Make sure the next character is '('.
  if (in.peek() != '(') {
    in.setstate(std::ios_base::failbit);
    return in;
  }
  in.get();

  // Try to read the next thing as a double.
  if (!(in >> realtmp)) {
    return in;
  }

  // Read the next three chars (' + ').
  if (in.get() != ' ')
    return in;
  if (in.get() != '+')
    return in;
  if (in.get() != ' ')
    return in;

  // Try to read the next token as a double ending in 'i'.
  std::string x;
  if (!getline(in, x, 'i')) {
    return in;
  }

  std::stringstream ss(x);
  if (!(ss >> imagtmp)) {
    return in;
  }

  // Verify the next char is ')'.
  if (in.peek() != ')') {
    in.setstate(std::ios_base::failbit);
    return in;
  }
  in.get();

  a.real_ = realtmp;
  a.imag_ = imagtmp;
  return in;
}

}  // namespace complex

testcomplex.cc

#include <iostream>
#include <sstream>

#include "Complex.h"

int main(int argc, char** argv) {
  // Invokes the constructors for a,b.
  complex::Complex a(1, 1), b(2, 2);
  complex::Complex c = b;  // Invokes the copy constructor for c.

  // Invokes the "+" operator; our implementation of the "+" operator
  // allocates a "temp" variable, so a constructor for it is invoked.
  // g++ has various optimizations including "return by value" that
  // can eliminate some of the potential copying implied by the code.
  // since we're assigning the return value from "+" to the variable
  // "d", instead of allocating "temp" in the stack frame of "+",
  // it could use the space allocated for "d" to hold temp's
  // contents, avoiding an extra copy constructor / allocation.
  // that's not guaranteed behavior and it might change from one
  // release of the compiler to another, but g++ will try to
  // reduce copying when it's safe.
  complex::Complex d = a + b;
  std::cout << "[address of d:] " << &d << std::endl;

  a = d;   // Invokes the "=" operator on a with argument d.
  b += a;  // Invokes the "+=" operator on b with argument a.

  c = 1 + c;  // invokes the symmetric "+" operator on Complex(1) and c
              // (implicit conversion from 1 using Complex(real) ctr)

  // Invokes the "<<" operator with args (cout, c), then (cout, endl).
  std::cout << c << std::endl;

  std::stringstream str("(10 + 11i)");

  // Invokes the ">>" operator with args (str, d).
  str >> d;

  // Invokes the "<<" operator with args (cout, d), then (cout, endl).
  std::cout << d << std::endl;

  return EXIT_SUCCESS;
}

heappoint.cc

#include <iostream>

#include "Point.h"

using std::cout;
using std::endl;

int* AllocateInt(int x) {
  int* heapy_int = new int;
  *heapy_int = x;
  // could also have been: int *heapy_int = new int(x);
  return heapy_int;
}

Point* AllocatePoint(int x, int y) {
  Point* heapy_point = new Point(x, y);
  return heapy_point;
}

int main(int argc, char** argv) {
  Point* x = AllocatePoint(1, 2);
  int* y = AllocateInt(3);

  cout << "x's x_ coordinate: " << x->get_x() << endl;
  cout << "distance between x and self: " << x->Distance(*x) << endl;
  cout << "y: " << y << ", *y: " << *y << endl;

  delete x;
  delete y;

  return EXIT_SUCCESS;
}

arrays.cc

#include <iostream>

#include "Point.h"

int main(int argc, char** argv) {
  int stack_int;      // stack-allocated int
  int* heap_int = new int;  // heap-allocated, uninitialized int
  int* heap_int_init = new int{12};  // heap-allocated, initialized to 12

  int stack_arr[3];  // stack-allocated array of 3 uninitialized ints
  int* heap_arr = new int[3];  // heap-allocated array of 3 uninitialized ints

  // Value initialize array elements (to zeros).
  int* heap_arr_init_val = new int[3]();  // heap-alloc array of 3 zeros

  // C++11: can use a braced list of element initializers.
  // if initializer list is short, remaining elements are value initialized.
  int* heap_arr_init_lst = new int[3]{4, 5};  // heap-alloc array of {4, 5, 0}

  Point stack_pt(1, 2);  // stack-allocated Point object.
  Point* heap_pt = new Point(1, 2);  // heap allocated Point object.

  // would be OK if we had a default constructor for Points, but
  // since we don't, the compiler complains.
  // Point *heap_pt_arr_err = new Point[2];  // heap-alloc, value initialized

  // C++11: can use a braced list of element initializers.
  Point* heap_pt_arr_init_lst = new Point[2]{1, 2}, {3, 4}; // missing an outer {} due to markdown error

  delete heap_int;                // correct
  delete heap_int_init;           // correct
  delete heap_pt;                 // correct
  delete heap_arr;                // incorrect!  should be delete[] heap_arr
  delete[] heap_arr_init_val;     // correct
  delete[] heap_pt_arr_init_lst;  // correct
  // memory leak of heap_arr_init_lst!

  return EXIT_SUCCESS;
}

Str.h

// Specification of a simple string class.
// A Str object wraps an ordinary C-string to make a C++ object with
// some basic operations.  Each str owns a dynamically allocated char
// array that holds the underlying \0-terminated C string.

#ifndef STR_H_
#define STR_H_

#include <iostream>    // for stream output

class Str {
 public:
  // constructors
  // create empty string
  Str();

  // create Str from c-string s
  Str(const char* s);

  // copy constructor - initialize this to be a copy of s
  Str(const Str& s);

  // destructor
  ~Str();

  // return length of this string
  int length() const;

  // return a new c-string allocated on the heap with
  // a copy of this Str's string data
  char* c_str() const;

  // append contents of s to the end of this string
  void append(const Str& s);

  // string assignment: replace this string with a copy of s
  Str& operator=(const Str& s);

  // stream output (global function, not class member)
  friend std::ostream& operator<<(std::ostream& out, const Str& s);

 private:
  // Str representation
  char* st_;        // c-string on heap with data bytes terminated by \0
};  // class Str

#endif  // STR_H_

Str.cc

// Implementation of a simple string class.
#include "Str.h"

#include <cstring>
#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

// Print trace messages with object addresses to show when functions get called.
#define TRACE(what)  cout << "- Str::" what << " called on " << this << endl

// constructors

Str::Str() {
  TRACE("default constructor");
  // allocate empty string
  st_ = new char[1];
  st_[0] = '\0';
}

Str::Str(const char* s) {
  TRACE("c-string constructor");
  int len = strlen(s);
  st_ = new char[len + 1];
  strncpy(st_, s, len + 1);
}

Str::Str(const Str& s) {
  TRACE("copy constructor");
  int len = strlen(s.st_);
  st_ = new char[len + 1];
  strncpy(st_, s.st_, len + 1);
}

// destructor
Str::~Str() {
  TRACE("destructor");
  delete [] st_;
}

// operations

int Str::length() const {
  TRACE("length");
  return strlen(st_);
}

char* Str::c_str() const {
  TRACE("c_str");
  int len = strlen(st_);
  char* result = new char[len + 1];
  strncpy(result, st_, len + 1);
  return result;
}


void Str::append(const Str& s) {
  TRACE("append");
  int len1 = strlen(st_);
  int len2 = strlen(s.st_);
  char* newst = new char[len1 + len2 + 1];
  strncpy(newst, st_, len1 + 1);
  strncat(newst, s.st_, len2);
  delete [] st_;
  st_ = newst;
}

Str& Str::operator=(const Str& s) {
  TRACE("assignment");
  // do nothing if trying to assign a string to itself
  if (this == &s) {
    return *this;
  }

  // Replace string array with one of correct size
  // (Note: this is where the self-assignment test _really_ matters)
  // (Note: a better implementation would re-use the existing array
  //  if it's long enough, but not too long)
  delete [] st_;
  int len = strlen(s.st_);
  st_ = new char[len + 1];

  // copy characters and return
  strncpy(st_, s.st_, len + 1);
  return *this;
}

// stream output
// (Note: not a member function of Str.  This is an overloaded global
// function that is a friend of Str so it can access private data)
ostream& operator<<(ostream& out, const Str& s) {
  out << s.st_;
  return out;
}

strtest.cc

// CSE 333 Lecture 12 demo: strtest.cc
// Hal Perkins

// Test program for a simple string class.
// Demonstrates string class with constructors, destructors,
// and assignment.  Trace output from Str.cc will show when
// the various constructors and destructor are called.

#include <iostream>

#include "Str.h"

using std::cout;
using std::endl;

// print message to show progress
void here(int n) {
  cout << "main: " << n << endl;
}

// id(x) == x (tests copy construtor)
Str id(Str s) {
  cout << "id: reached start of code" << endl;
  return s;
}

// create some strings and play with them
int main() {
  // local variables in main's stack frame
  // (destructors called when main exits)
  Str s1, s2;            // default constructors
  Str hello("hello");    // c-string constructor
  Str howdy = hello;     // copy constructor

  here(1);

  // get c-string from Str
  char* hi = howdy.c_str();
  cout << hi << endl;
  delete [] hi;

  here(2);

  // test append (constructs a Str argument and discards it)
  hello.append(" there");
  cout << hello << endl;
  cout << "  length is " << hello.length() << endl;

  here(3);

  // assignment operator and Str(char *) constructor
  s1 = "howdy";
  cout << s1 << endl;

  here(4);

  // copy constructors
  s2 = id(hello);
  cout << s2 << endl;

  here(5);

  // heap allocated Str object
  // (same general idea as a Java String, but in C++)
  // (init here with copy constructor; destructor called when Str deleted)
  // (uses overloaded << operator for Str)
  Str* h = new Str(hello);
  h->append(" cse333!");
  cout << "Str at " << h << " = \"" << *h << "\"" << endl;
  cout << "  length is " << h->length() << endl;
  delete h;

  here(6);

  // Enough already!!
  return EXIT_SUCCESS;
}