Programming in C and C++ (2020/21)
Supervision 2

1

If a function f has a static instance of a class as a local variable, when is the class constructor called?


2

Write a class Matrix which allows a programmer to define 2 × 2 matrices. Overload the common operators (e.g. +, -, *, and /). Can you easily extend your design to matrices of arbitrary size?


3

Write a class Vector which allows a programmer to define a vector of length two. Modify your Matrix and Vector classes so that they interoperate correctly (e.g. v2 = m*v1 should work as expected).


4

Using meta programming, write a templated class Prime, which evaluates whether a literal integer constant (e.g. 7) is prime or not at compile time.

How can you be sure that your implementation of class Prime has been evaluated at compile time?


5

Write a class LinkedList which stores zero or more positive integers internally as a linked list on the heap. The class should provide appropriate constructors and destructors and a method pop() to remove items from the head of the list. The method pop() should return -1 if there are no remaining items. Your implementation should override the copy constructor and assignment operator to copy the linked list structure between class instances. You might like to test your implementation with the following:

int main() {
    int test[] = {1,2,3,4,5};
    LinkList l1(test+1,4), l2(test,5);
    LinkList l3 = l2, l4;
    l4 = l1;
    printf("%d %d %d\n", l1.pop(), l3.pop(), l4.pop());
    return 0;
}

Hint: heap allocation and deallocation should occur exactly once!

6

Why should destructors in an abstract class almost always be declared virtual?

7

Provide an implementation for:

    Stack(const Stack& s);
    Stack& operator=(const Stack& s);

as declared in the slides for lecture 12.

8

Provide an implementation for:

    template<class T> T Stack<T>::pop();
    template<class T> Stack<T>::~Stack();

as declared in the slides for lecture 12.

9

A hardware engineer stores a FIFO queue of bits in an int on a platform with
32-bit ints and 8-bit chars using the following C++ class:

class BitQueue {
    int valid_bits; // the number of valid bits held in queue
    int queue;      // least significant bit is most recent bit added
public:
    BitQueue(): valid_bits(0), queue(0) {}
    void push(int val, int bsize);
    int pop(int bsize);
    int size();
};
  1. Write an implementation of BitQueue::size which should return the number
    of bits currently held in queue.

  2. Write an implementation of BitQueue::push which places the bsize least
    significant bits from val onto queue and updates valid_bits. An
    exception should be thrown in cases where data would otherwise be lost.

  3. Write an implementation of BitQueue::pop, which takes bsize bits from
    queue, provides them as the bsize least significant bits in the return
    value, and updates valid_bits. An exception should be thrown when any
    requested data is unavailable.

  4. The hardware engineer has built a communication device together with a C++
    library function send to transmit data with the following declaration:
    void send(char);
    Use the BitQueue class to write a C++ definition for:

     void sendmsg(const char* msg);
            

    Each of the characters in msg should be encoded, in index order, using the
    following binary codes: 'a'=0, 'b'=10, 'c'=1100, and 'd'=1101. All
    other characters should be ignored. Successive binary codes should be
    bit-packed together and the code 111 should be used to denote the end of
    the message. Chunks of 8-bits should be sent using the send function and any
    remaining bits at the end of a message should be padded with zeros. For
    example, executing

     sendmsg("abcd");
            

    should call the send function twice, with the binary values 01011001
    followed by 10111100.