Question #1. Constructors & Destructor
Given the following class definitions, write down the output of the following
program segment and explain each line of output:
class C {
public:
C() {
cout << "C::C()" << endl;
}
C(int) {
cout << "C::C(int)" << endl;
}
C(const C&) {
cout << "C::C(const C&)" << endl;
}
C& operator=(const C&) {
cout << "C::operator=(const C&)" << endl;
return *this;
}
~C() {
cout << "C::~C()" << endl;
}
};
C func(C c1) {
C c2(5);
c2 = c1;
return c2;
}
CODE SEGMENT:
...
{
C c1,c2;
c2 = func(c1);
}
...
C::C() c1 constructed
C::C() c2 constructed
C::C(const C&) c1 passed by value to func
C::C(int) local c2 in func constructed
C::operator=(const C&) assignment in c2 = c1
C::C(const C&) copy of c2 constructed, return by value
C::~C() local c2 gone, func ends
C::~C() c1 passed gone
C::operator=(const C&) c2 = func(c1)
C::~C() copy returned by func
C::~C() c2 leaves scope
C::~C() c1 leaves scope
Question #2. Constructors and Destructors with Inheritance.
Consider the following definitions. Give the OUTPUT of the following program
segment, and briefly explain what caused the line to be printed
int A = 3;
class Base {
public:
Base() {
A = A + 2;
cout << "Base::Base()" << endl;
}
Base(const Base&) {
A = A - 1;
cout << "Base::Base(const Base&)" << endl;
}
~Base() {
A = 2*A;
cout << "Base::~Base()" << endl;
}
};
class Derived: public Base {
public:
Derived() {
A = 3*A;
cout << "Derived::Derived()" << endl;
}
Derived(const Derived& d):Base(d) {
A = A - 2;
cout << "Derived::Derived(const Derived&)" << endl;
}
~Derived() {
A = A + 4;
cout << "Derived::~Derived" << endl;
}
};
....
{
Derived d1, d2(d1);
}
cout << "A = " << A << endl;
...
Base::Base() constructing d1, Derived calls Base
Derived::Derived() constructing d1
Base::Base(const Base&) constructing d2, Derived calls Base
Derived::Derived(const Derived&) constructing d2
Derived::~Derived destructor of Derived calls ~Base
Base::~Base() d2 leaving scope
Derived::~Derived destructor of Derived calls ~Base
Base::~Base() d1 leaving scope
A= 72 (2 *((2*((((3 *(3+2))-1)-2)+4)) + 4))
Question #3
Given the following definitions for class stack, implement methods push,
pop and empty:
struct stack_node {
int element;
stack_node* next;
};
class stack {
// LINKED STACK:
// stack S;
// S.push(3); S.push(5); S.push(2); -->
//
// S.top->element = 2
// ->next -> element = 5
// -> next -> element = 3
// -> next = NULL;
// S.pop() == 2
// S.pop() == 5
// S.pop() == 3
// S.empty() == true
private:
stack_node * top;
public:
stack():top(NULL) {
}
~stack() {
while(!empty()) pop();
}
void push(int); // YOU IMPLEMENT IT!
int pop(); // YOU IMPLEMENT IT!
bool empty() const; // YOU IMPLEMENT IT!
};
void stack::push(i) {
stack_node * n = new stack_node;
n->element = i;
n->next = top;
top = n;
}
int stack::pop() {
if (empty()) {
cerr << "CANNOT POP EMPTY STACK!" << endl;
// throw exception or exit()
// just do something
}
int v = top->element;
stack_node *tmp = top;
or top = top->next
delete tmp;
return v;
}
bool stack::empty() const {
return top == NULL;
}
Question 4
Implement a string class. The Sting class is a wrapper for a char*.
Implement the copy constructor (1), destructor (2) and method length
(3). Overload operator<< (4) and operator+ (5). For
strings
s1("hello"), s2(" world") s3 = s1 + s2;
s3 becomes "hello world", while s1 and s2
remain unchanged. operator<< prints the string to an output
stream. The implementation of the default constructor, should help you
understand how an instance of class String is represented. You may use:
int strlen(char* s); // returns the length of s
void strcpy(char* s1, char* s2); // copies the characters from
// s2 into s1
class String {
private:
char* s; // 0 byte terminated, dynamic array of characters
public:
String(char* =NULL); // default and one argument constructor
// IMPLEMENT THE METHODS BELOW:
String(const String&); // copy constructor
// return a new string, which is obtained by
// appending the argument string to a copy of s
String operator+(const String&) const;
~String(); // destructor
int length() const; // length of string
friend ostream& operator<<(ostream&,const String&);
};
String::String(char* str) {
if (str == NULL) {
s = str;
return;
}
s = new char[strlen(str)+1];
strcpy(s,str);
}
String::String(const String& str) {
if (str.s == NULL) {
s = NULL;
return;
}
s = new char[str.length()+1];
strcpy(s,str.s);
}
String::~String() {
delete [] s;
}
String String::operator+(const String& str) const {
String ns;
ns.s = new char[length() + str.length() + 1];
strcpy(ns.s,s);
strcpy(&(ns.s[length()]),str.s);
return ns;
}
int String::length() const {
return strlen(s);
}
ostream& operator<<(ostream& os,const String& str) {
return os << str.s;
}
Question #5
Outline your contribution to the project. Select one aspect of your work that
you found was the most important and describe it. (Feel free to use diagrams
and C++ code segments, 10-12 sentences are sufficient).
Whatever you did ...
Question #6
Implement
bool find_digit(unsigned int n, unsigned int k);
which returns true if and only if digit k occurs in n.
(Hint: for integers a = 7 ,b = 3,c
c = a % b // modulus, c = 1
c = a / b // integer division, c = 2)
bool find_digit(unsigned int n, unsigned int k) {
if (n / 10 == 0) return n == k;
else return n % 10 == k ? true : find_digit(n/10,k);
}
While the recursive solution is the most obvious you could also have used a for,
while or do-while loop (as far as it works!)
bool find_digit(unsigned int n, unsigned int k) {
while (n/10 != 0) {
if (n%10 == k) return true;
n = n/10;
}
return n == k;
}
Question #7
Implement a recursive function
int sum(int b[], int k)
which calculates the sum of the elements stored in array b of length k
You may assume k >= 1
int sum(int b[], int l) {
return l == 1 ? b[0] : b[l-1] + sum(b,l-1);
}
Question #8
Give the output of the following program segment!
To receive partial marks, indicate where p1, p2, pp1 and pp2
point after each assignment, in case you get the output wrong!
int a = 7, b = 3,
*p1, *p2,
**pp1, **pp2;
p1 = &a; // p1->a
p2 = &b; // p2->b
pp1 = &p1; // pp1->p1
pp2 = &p2; // pp2->p2
**pp1 = **pp2 + b; // a = b + b = 6
cout << "a = " << a << " b = " << b << endl;
*pp2 = &a; // p2->a
**pp1 = *p2 - b; // a = a - b = 3
cout << "a = " << a << " b = " << b << endl;
p2 = *pp1; // p2 = p1 -> a
b = *p1 - **pp2; // b = a - a = 0
cout << "a = " << a << " b = " << b << endl;
a = 6 b = 3
a = 3 b = 3
a = 3 b = 0
กก