NivaarExam PrepOfficial exam papers ↗

25-Comp-A4 Program Design and Data Structures · May 2013

Question 4 of 8: Object-Oriented Design

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

National Exams — May 2013 — 98-Comp-A4 Program Design and Data Structures. Three-hour, closed-book exam, no calculator permitted. Format: eight questions, candidates answer any five (all questions equal weight; only the first five appearing in the answer book are marked). Pseudocode or a high-level language (C or C++) is acceptable throughout — marking emphasizes program operation, not syntactic detail. All eight questions are solved below for completeness. No marks breakdown per sub-part is given on the source paper beyond the "equal weight" instruction.

Reference texts: Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms (3rd ed., MIT Press) — algorithm design, complexity analysis, sorting; Weiss, Data Structures and Algorithm Analysis in C (2nd ed., Pearson) — linked lists, stacks, pointer-based structures; Deitel & Deitel, C++ How to Program (9th ed., Pearson) — classes, templates, operator overloading; Kernighan & Ritchie, The C Programming Language (2nd ed.) — file I/O and arrays.

Question 4: Object-Oriented Design

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

Approach. A template class wraps a dynamically allocated array of the element type plus its length; operator[] gives read/write element access, and the arithmetic/equality operators are declared as members that check size compatibility first and either report an error or apply the operation element-wise. Assumption: "multiplication" of two vectors is taken as the inner (dot) product, returning a scalar of type T — the only vector×vector product that is always well-defined regardless of dimension, and consistent with "produces an error if not the same size" (element-wise product would need the same size check anyway, but the dot product is the operation actually used in the engineering applications the question motivates).

Vector.h

#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <cstdlib>

template <class T>
class Vector {
public:
    explicit Vector(int size);            // uninitialized elements
    Vector(const Vector<T>& other);       // copy constructor
    Vector<T>& operator=(const Vector<T>& other);
    ~Vector();

    T& operator[](int index);             // read/write access
    const T& operator[](int index) const;

    Vector<T> operator+(const Vector<T>& rhs) const;
    Vector<T> operator-(const Vector<T>& rhs) const;
    T operator*(const Vector<T>& rhs) const;   // dot product
    bool operator==(const Vector<T>& rhs) const;

    void print(std::ostream& os = std::cout) const;
    int size() const { return n; }

private:
    T* data;
    int n;
    void require_same_size(const Vector<T>& other, const char* op) const;
};

#endif

Vector.cc

#include "Vector.h"

template <class T>
Vector<T>::Vector(int size) : data(new T[size]), n(size) {}

template <class T>
Vector<T>::Vector(const Vector<T>& other) : data(new T[other.n]), n(other.n) {
    for (int i = 0; i < n; i++) data[i] = other.data[i];
}

template <class T>
Vector<T>& Vector<T>::operator=(const Vector<T>& other) {
    if (this == &other) return *this;
    delete[] data;
    n = other.n;
    data = new T[n];
    for (int i = 0; i < n; i++) data[i] = other.data[i];
    return *this;
}

template <class T>
Vector<T>::~Vector() { delete[] data; }

template <class T>
T& Vector<T>::operator[](int index) { return data[index]; }

template <class T>
const T& Vector<T>::operator[](int index) const { return data[index]; }

template <class T>
void Vector<T>::require_same_size(const Vector<T>& other, const char* op) const {
    if (n != other.n) {
        std::cerr << "Vector error: operator" << op
                   << " requires equal-size operands ("
                   << n << " vs " << other.n << ")\n";
        std::exit(1);
    }
}

template <class T>
Vector<T> Vector<T>::operator+(const Vector<T>& rhs) const {
    require_same_size(rhs, "+");
    Vector<T> result(n);
    for (int i = 0; i < n; i++) result[i] = data[i] + rhs.data[i];
    return result;
}

template <class T>
Vector<T> Vector<T>::operator-(const Vector<T>& rhs) const {
    require_same_size(rhs, "-");
    Vector<T> result(n);
    for (int i = 0; i < n; i++) result[i] = data[i] - rhs.data[i];
    return result;
}

template <class T>
T Vector<T>::operator*(const Vector<T>& rhs) const {
    require_same_size(rhs, "*");
    T sum = data[0] * rhs.data[0];
    for (int i = 1; i < n; i++) sum = sum + data[i] * rhs.data[i];
    return sum;
}

template <class T>
bool Vector<T>::operator==(const Vector<T>& rhs) const {
    if (n != rhs.n) return false;
    for (int i = 0; i < n; i++)
        if (data[i] != rhs.data[i]) return false;
    return true;
}

template <class T>
void Vector<T>::print(std::ostream& os) const {
    os << "(";
    for (int i = 0; i < n; i++) os << data[i] << (i + 1 < n ? ", " : "");
    os << ")";
}

// explicit instantiation for the three required element types
template class Vector<int>;
template class Vector<float>;
template class Vector<double>;
OperationBehaviour on size mismatch
operator+, operator-, operator* (dot product)error message to std::cerr, program exits
operator==returns false (size mismatch means "not equal," not an error)
Element access v[i]read and write, via non-const/const overloads