0% found this document useful (0 votes)
25 views

Assignment - 3 Solution

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

Assignment - 3 Solution

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Programming in Modern C++: Assignment Week 3

Total Marks : 25

Partha Pratim Das


Department of Computer Science and Engineering
Indian Institute of Technology Kharagpur, Kharagpur – 721302
[email protected]

July 31, 2024

Question 1
Consider the following code segment. [MCQ, Marks 2]

class Rectangle{
private:
int width, height;
public:
void setWidth(int w){ width = w; }
void setHeight(int h){ height = h; }
void display(){ cout << width << " x " << height; }
void doubleSize(){ width *= 2; height *= 2; }
int increaseWidth(){ return width + 1; }
int increaseHeight(){ return ++height; }
};

Identify the set of all the methods that change the state of the class Rectangle objects.

a) setWidth(), setHeight(), display()

b) setWidth(), setHeight(), doubleSize(), increaseHeight()

c) setWidth(), setHeight(), doubleSize(), increaseWidth(), increaseHeight()

d) setWidth(), setHeight(), increaseWidth(), increaseHeight()

Answer: b)
Explanation:
The function setWidth() changes the data member value width. Thus, setWidth() changes
the state of the object.
The function setHeight() changes the data member value height. Thus, setHeight()
changes the state of the object.
The function doubleSize() changes the values of data members width and height. Thus,
doubleSize() changes the state of the object.
The function increaseHeight() changes the value of data member height. Thus, increaseHeight()
changes the state of the object.
Note that, the function increaseWidth() does not change the value of data member width,
as it returns an expression only i.e. (width + 1).

1
Question 2
Consider the following code segment. [MCQ, Marks 2]

#include <iostream>
using namespace std;

class Example {
int x;
public:
Example(int x_ = 0) : x(x_) { cout << "Constructor:" << x << " "; }
~Example() { cout << "Destructor:" << x << " "; }
};

Example globalObj(50); // LINE-1

int main() {
Example *pExample = new Example(20); // LINE-2
Example localObj1(30); // LINE-3
{
Example localObj2(40); // LINE-4
delete pExample; // LINE-5
} // LINE-6
return 0;
} // LINE-7

What will be the output?

a) Constructor:50 Constructor:20 Constructor:30 Constructor:40 Destructor:40


Destructor:30 Destructor:20 Destructor:50

b) Constructor:20 Constructor:50 Constructor:30 Constructor:40 Destructor:40


Destructor:30 Destructor:50 Destructor:20

c) Constructor:50 Constructor:20 Constructor:40 Constructor:30 Destructor:30


Destructor:40 Destructor:20 Destructor:50

d) Constructor:50 Constructor:20 Constructor:30 Constructor:40 Destructor:20


Destructor:40 Destructor:30 Destructor:50

Answer: d)
Explanation:
The object (globalObj) defined at LINE-1 has a global scope, so this object will be created
even before the main() function starts. It calls the constructor and prints Constructor: 50.
Then, within main() another object gets instantiated at LINE-2, and it calls the constructor
and prints Constructor: 20.
At LINE-3, an object localObj1 gets instantiated, which calls the constructor and prints
Constructor: 30.
At LINE-4, an object localObj2 gets instantiated within a block scope, and calls the construc-
tor and it prints Constructor: 40.
At LINE-5, the object pExample (which was created at LINE-2) gets deleted, so it calls the
destructor and prints Destructor: 20.
At LINE-6, the block scope ends. Thus, the local object localObj2 (which was created at
LINE-4) gets deleted. It calls the destructor and prints Destructor: 40.

2
At LINE-7, the scope of the main() function ends. Thus, the local object localObj1 (which
was created at LINE-3) gets deleted. It calls the destructor and prints Destructor: 30.
At the end of the program, the object globalObj having a global scope gets deleted. It calls
the destructor and prints Destructor: 50.

3
Question 3
Consider the following class. [MCQ, Mark 1]

class Sample {
________:
int a;
________:
int b;
/* Some more code */
};

Fill in the blanks with proper access specifiers so that member b can be accessed from outside
of the class but member a cannot be accessed.

a) public, public

b) private, public

c) public, private

d) private, private

Answer: b)
Explanation:
A class member should be declared as public to be accessed from outside of the class. On the
other hand, a private data member prevents itself from being accessed directly from outside of
the class. Therefore, member a should be private and member b should be public.

4
Question 4
Consider the code segment below. [MCQ, Marks 2]
#include <iostream>
using namespace std;

int globalVar = 5;

class MyClass {
int memberVar;
public:
MyClass(int memberVar_ = 0) : memberVar(++memberVar_) { ++globalVar; } // LINE-1
~MyClass() { memberVar = 0; globalVar = 0; }
void display() {
cout << "memberVar = " << memberVar << ", globalVar = " << globalVar << endl;
}
};

void function() {
MyClass obj;
obj.display();
}

int main() {
MyClass obj;
function();
obj.display();
return 0;

}
What will be the output?
a) memberVar = 6, globalVar = 7
memberVar = 1, globalVar = 8
b) memberVar = 1, globalVar = 7
memberVar = 1, globalVar = 0
c) memberVar = 1, globalVar = 8
memberVar = 1, globalVar = 0
d) memberVar = 1, globalVar = 7
memberVar = 2, globalVar = 0
Answer: b)
Explanation:
The statement MyClass obj; in main() calls the constructor at LINE-1, which makes memberVar
= 1 and globalVar = 6.
Then the statement MyClass obj; in function() calls the constructor at LINE-1, which
makes memberVar = 1 and globalVar = 7.
Then the statement obj.display(); in function() prints memberVar = 1, globalVar = 7.
As the function function() returns, the destructor for the local object obj is called, which
makes memberVar = 0 and globalVar = 0.
Finally, the statement obj.display(); in main() prints memberVar = 1, globalVar = 0.

5
Question 5
Consider the following code segment. [MCQ, Marks 1]

#include <iostream>
using namespace std;

int globalVar = 0;

class Example {
public:
Example() { globalVar = 5; }
~Example() { globalVar = 6; }
};

void someFunction() {
Example ex;
}

int anotherFunction() {
globalVar = 7;
someFunction();
return globalVar++;
}

int main() {
cout << anotherFunction() << " ";
cout << globalVar << endl;
return 0;
}

What will be the output?

a) 5 6

b) 7 5

c) 6 7

d) 7 8

Answer: c)
Explanation:
globalVar is initialized to 0 (globalVar = 0; executes before main() is called). Then
main() starts and calls anotherFunction() which sets globalVar to 7 by globalVar = 7;.
The anotherFunction() calls the function someFunction(). In function someFunction(),
Example ex sets globalVar = 5. But the object ex is local within function someFunction().
So, as the function someFunction() returns, the destructor of local object ex will be called
before return and globalVar becomes 6. This 6 will be returned by anotherFunction(), and
gets printed.
Further, globalVar value is incremented to 7 after return (since globalVar++ is post-increment).
Finally, the value of globalVar is printed as 7.
Hence the correct option is c).

6
Question 6
Consider the code segment below. [MCQ, Marks 2]

#include <iostream>
using namespace std;

class Sample {
int x, y, z;
public:
Sample(int val = 0) : z(++val), y(val++), x(++val) {}
void display() {
cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}
};

int main() {
Sample obj(5);
obj.display();
return 0;
}

What will be the output?

a) x = 8, y = 6, z = 6

b) x = 6, y = 6, z = 8

c) x = 8, y = 7, z = 6

d) x = 6, y = 7, z = 8

Answer: b)
Explanation:
The order in which the data members are initialized in an initialization list follows the order
of declaration of the data members.
Since z is declared first, z gets initialized to ++val i.e. 6.
Then y gets initialized to val++ i.e. 6. However, the value of val becomes 7.
Finally, x gets initialized to ++val i.e. 8.

7
Question 7
Consider the code segment below. [MCQ, Marks 2]

#include <iostream>
using namespace std;

class Car {
int id;
string model;
Car(){} // LINE-1
public:
Car(int id_, string model_) : id(id_), model(model_) {}
void updateCar(Car& c) {
this->id = c.id;
this->model = c.model;
} // LINE-2
void display() {
cout << id << ", " << model << endl;
}
};

int main() {
Car car1(101, "Sedan");
Car car2(202, "SUV");
car1.updateCar(car2);
car1.display();
return 0;
}

What will be the output/error?

a) 101, Sedan

b) 202, SUV

c) Compiler error at LINE-1: Car::Car() cannot be private

d) Compiler error at LINE-2: lvalue required as left operand of assignment

Answer: d)
Explanation:
Since this is a constant pointer, any attempt to modify it (at LINE-2) results in a compiler
error.

8
Question 8
Consider the code segment below. [MCQ, Marks 2]

#include <iostream>
using namespace std;

class Rectangle {
int width, height;
public:
Rectangle(int width_ = 0, int height_ = 0) : width(width_), height(height_) {
cout << "ctor ";
} // LINE-1

Rectangle(Rectangle &r) : width(r.width), height(r.height) {


cout << "c-ctor ";
} // LINE-2

Rectangle& operator=(Rectangle r) {
width = r.width;
height = r.height;
cout << "c-assign ";
return *this;
} // LINE-3
};

int main() {
Rectangle r1(30, 40);
Rectangle r2 = r1;
Rectangle *rPtr;
Rectangle r3;
r3 = r2;
return 0;
}

What will be the output/error?

a) ctor c-ctor ctor c-ctor

b) ctor c-ctor ctor c-assign

c) ctor c-ctor ctor c-ctor c-assign

d) ctor c-assign ctor c-assign

Answer: c)
Explanation:
The statement Rectangle r1(30, 40); invokes the constructor at LINE-1 and prints ctor.
The statement Rectangle r2 = r1; invokes the copy constructor at LINE-2 and prints c-ctor.
The statement Rectangle *rPtr; does not create an object.
The statement Rectangle r3; invokes the constructor at LINE-1 and prints ctor.
The statement r3 = r2; calls the copy assignment function. Since it passes r2 as pass by
value, it invokes the copy constructor at LINE-2 and prints c-ctor. Then it executes the body
of the copy assignment function (at LINE-3) and prints c-assign.

9
Question 9
Consider the following code segment. [MCQ, Marks 2]

#include<iostream>
using namespace std;

class Demo {
int y;
public:
Demo(int b=0) : y(b){ cout << "First "; }
Demo(const int &j) : y(j){ cout << "Second "; }
};

int main() {
Demo d1 = 10;
return 0;
}

What will be the output/error?

a) First

b) Second

c) First Second

d) Compilation error: conversion from ’int’ to ’Demo’ is ambiguous

Answer: d)
Explanation:
Both the constructors take an integer as input and assign it to the data member of the class. So,
when the assignment of an integer to the class object is done, the compiler becomes confused
about which constructor to call. Hence, it gives an error.

10
Programming Questions

Question 1
Marks: 3
Consider the following program. Fill in the blanks as per the instructions given below:

• at LINE-1 with an appropriate initialization block to initialize the data members,

• at LINE-2 with an appropriate definition of the destructor to free the memory allocated
for the data members,

• at LINE-3 and LINE-4 with appropriate definitions of the functions getA() and getB().

such that it will satisfy the given test cases.

#include<iostream>
using namespace std;

class Pair {
const int *a, *b;
public:
Pair(int val1, int val2) : _________________________{} //LINE-1
~Pair(){ __________________________________________ } //LINE-2
int getA(){ _______________________________________ } //LINE-3
int getB(){ _______________________________________ } //LINE-4
};

int main(){
int x, y;
cin >> x >> y;
Pair p(x, y);
cout << "[" << p.getA() << ", " << p.getB() << "]";
return 0;
}

Public 1
Input: 3 4
Output: [3, 4]

Public 2
Input: 7 8
Output: [7, 8]

Private
Input: 15 25
Output: [15, 25]

Answer:
LINE-1: a(new int(val1)), b(new int(val2))
LINE-2: delete a; delete b;
LINE-3: return *a;

11
LINE-4: return *b;
Explanation:
Since the data members are pointer types, the constructor must allocate memory and initialize
them. Thus, the definition of the constructor can be as follows:
Pair(int val1, int val2) : a(new int(val1)), b(new int(val2)) //LINE-1
The destructor must free the memory allocated for the data members. Thus, the definition of
the destructor can be as follows:
Pair() delete a; delete b; //LINE-2
The functions getA() and getB() must return the values pointed to by the data members a
and b respectively. Thus, the definitions of the functions can be as follows:
int getA() return *a; //LINE-3
int getB() return *b; //LINE-4

12
Question 2
. Marks: 3
Consider the following program. Fill in the blanks as per the instructions given below:
• at LINE-1 with appropriate declaration of the data member total,

• at LINE-2 and LINE-3 with appropriate headers for the functions calculateTotal()
and display()
such that it will satisfy the given test cases.

#include<iostream>
using namespace std;

class Calculator {
int a, b;
__________________; //LINE-1
public:
Calculator(int a_, int b_) : a(a_ * 2), b(b_ * 2){}
__________________________________ { total = a + b; }; //LINE-2
__________________________________ { //LINE-3
cout << "a = " << a << ", b = " << b << ", total = " << total;
}
};

int main(){
int x, y;
cin >> x >> y;
const Calculator calc(x, y);
calc.calculateTotal();
calc.display();
return 0;
}

Public 1
Input: 4 6
Output: a = 8, b = 12, total = 20

Public 2
Input: 7 -3
Output: a = 14, b = -6, total = 8

Private
Input: 15 10
Output: a = 30, b = 20, total = 50

Answer:
LINE-1: mutable int total
LINE-2: void calculateTotal() const
LINE-3: void display() const
Explanation:

13
Since calc is defined as a constant object, and we need to modify the value of total, total
has to be defined as a mutable member. Thus, the declaration of total can be as follows:
LINE-1: mutable int total
Since the functions calculateTotal() and display() are called on a constant object, they
must be defined as constant functions as follows:
LINE-2: void calculateTotal() const
LINE-3: void display() const

14
Question 3
Marks: 3
Consider the following program. Fill in the blanks as per the instructions given below:

• at LINE-1 with the appropriate definition of the copy constructor,

• at LINE-2 with the appropriate definition of the copy assignment operator,

• at LINE-3 with the appropriate condition to check for self-assignment.

such that it will satisfy the given test cases.

#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;

class Student {
int sid;
char *name;
public:
Student(int sid_, const char *name_) : sid(sid_), name(strdup(name_)) {}
_______________________ : sid(s.sid), name(strdup(s.name)) { } //LINE-1
________________________________________ { //LINE-2
if (_____________________) { //LINE-3
free(name);
sid = s.sid;
name = strdup(s.name);
}
return *this;
}
void display(){
cout << sid << " : " << name << endl;
}
};

int main(){
int a, b;
char n1[80], n2[80];
cin >> a >> n1 >> b >> n2;
Student s1(a, n1);
Student s2 = s1;
Student s3(b, n2);
s1 = s3;
s1.display();
s2.display();
s3.display();
return 0;
}

15
Public 1
Input:
5 John
10 Alice
Output:
10 : Alice
5 : John
10 : Alice

Public 2
Input:
20 Bob
25 Carol
Output:
25 : Carol
20 : Bob
25 : Carol

Private
Input:
30 Dave
35 Eve
Output:
35 : Eve
30 : Dave
35 : Eve

Answer:
LINE-1: Student(const Student& s)
LINE-2: Student& operator=(const Student& s)
LINE-3: this != &s
Explanation:
At LINE-1, the header of the copy constructor must be as follows: LINE-1: Student(const
Student& s)
At LINE-2, the header of the copy assignment operator must be as follows: LINE-2: Student&
operator=(const Student& s)
At LINE-3, the condition must check for self-assignment which can be done using the code as
follows:
LINE-3: this != &s

16

You might also like