Merged Assignment Programming in Mordern C++ All Answers
Merged Assignment Programming in Mordern C++ All Answers
Total Marks : 30
June 3, 2023
Question 1
Consider the below code snippet. [MCQ, Marks 2]
#include <stdio.h>
int main() {
printf("%u", sizeof(array));
return 0;
}
What will be the output/error (sizeof(double) = 8 bytes)?
a) 40 2.00
b) 120 5.00
c) 120 2.00
Note: Default initialization of the array element is 0.00 though it varies from compiler to
compiler.
1
Question 2
Consider the following code segment. [MCQ, Marks 2]
#include <stdio.h>
enum Covid_prevention {
Sanitizer = 1,
Wear_mask = 2,
Soc_distance = 4
};
int main() {
int myCovidPrevention = Wear_mask | Soc_distance;
printf("%d", myCovidPrevention);
return 0;
}
a) 2
b) 4
c) 6
d) 8
Answer: c)
Explanation:
The enum value Wear mask and Soc distance are assigned with a bitwise OR (The pipe
symbol, |) operator to the integer variable myCovidPrevention. So value of Wear mask |
Soc distance = 2 | 4 = 000010 | 000100 = 000110 = 6.
Note that, int is of 4 bytes though we are considering the right most six bits for calculation
and ignore all zeros in the left.
2
Question 3
Consider the below program. [MCQ, Marks 2]
#include <stdio.h>
int main() {
int x = 1;
switch(x)
{
case x:
printf("case 1 ");
break;
case x + 1;
printf("case 2 ");
break;
default:
printf("default block");
break;
}
return 0;
}
a) case 1
b) case 2
c) default block
Answer: d)
Explanation:
The case statement accepts only an int or char constant expression. As the case statement
is having variable i.e. not constant expression, the program will give compilation error.
3
Question 4
Consider the following linked list: [MCQ, Marks 2]
What is the output of the following function when it is called with the head of the list?
a) I T G I G
b) I T G G
c) I T G G T I
d) I T G I T G
Answer: c)
Explanation:
fun() prints alternate nodes of the given Linked List, first from head to end, and then from
end to head. If the Linked List has an even number of nodes, then skips the last node.
4
Question 5
A single array A[1..MAXSIZE] is used to implement two stacks. The two stacks grow from
opposite ends of the array. Variables t1 and t2 (tl < t2) point to the location of the topmost
element in each of the stacks. If the space is to be used efficiently, the condition for stack full
is: [MCQ, Marks 2]
b) t1 + t2 = MAXSIZE
d) t1 = t2 - 1
Answer: d)
Explanation:
If we are to use space efficiently, then the size of the any stack can be more than MAXSIZE/2.
Both stacks will grow from both ends and if any of the stack top reaches near to the other top
then the stacks are full. So the condition will be t1 = t2 -1 (given that t1 ≤ t2)
5
Question 6
Consider the following code segment. [MCQ, Marks 2]
Stack Stk;
while (!isEmpty(que)) {
push(&Stk, deQueue(que));
}
while (!isEmpty(&Stk)) {
enQueue(que, pop(&Stk));
}
}
where push and pop are two standard functionalities of stack data structure. Similarly, enQueue
and deQueue are two standard functionalities of queue data structure to insert and delete the
items respectively. And isEmpty checks if the stack or the queue is empty or not.
Answer: b)
Explanation:
The function takes a queue que as an argument. It dequeues all items of que and pushes them
to a stack Stk. Then pops all items of Stk and enqueues the items back to que. Since stack is
LIFO order, all items of queue are reversed.
6
Question 7
Consider the below code segment. [MCQ, Marks 2]
#include <stdio.h>
int main() {
int x = 1;
int y;
y = (x=x+5, x*5);
printf("%d",y);
return 0;
}
a) 25
b) 30
c) 6
d) 5
Answer: b)
Explanation:
Comma operator evaluates multiple expressions from left to right. The value of rightmost
(x*5) expression is assigned to y. Here first x=x+5 will be evaluated and make the value of x
as 6. Then second expression x*5 will be evaluated and 6*5=30 will be assigned to y.
7
Question 8
Consider a three-dimensional array arr[5][10][20]. An element from this array can be
represented as arr[i][j][k] where 0 ≤ i ≤ 4, 0 ≤ j ≤ 9 and 0 ≤ k ≤ 19. How can you write
arr[2][6][10] in an equivalent pointer expression? [MSQ, Marks 2]
a) ((**(*a+2)+6)+10)
b) (**(*(a+2)+6)+10)
c) (*(**(a+2)+6)+10)
d) *(*(*(a+2)+6)+10)
Answer: d)
Explanation:
C represents an array as row-major. As a multidimensional array is stored in one dimensional
fashion in memory, the innermost index is the slowest to change. Hence, the equivalent pointer
which points to the element arr[i][j][k] is *(*(*(a+i)+j)+k). Hence, the correct option
is d).
8
Question 9
Consider the code segment below. [MCQ, Marks 2]
#include <stdio.h>
int main() {
int *p, n = 5;
p = &n;
*p += 1;
return 0;
}
a) 5,5
b) 5,6
c) 6,5
d) 6,6
Answer: d)
Explanation:
The address of variable n is assigned to the pointer variable p. So, whatever changes are done
in pointer variable will be reflected to n. The value of *p is incremented by 1. So, the value of
n will also be incremented by 1. Hence, output will be 6,6.
9
Question 10
Consider the code segment below. [MCQ, Marks 2]
#include <stdio.h>
struct result {
char subject[20];
int mark;
};
int main() {
struct result r[] = {
{"Maths",95},
{"Science",93},
{"English",80}
};
printf("%s ", r[1].subject);
printf("%d", (*(r+2)).mark);
return 0;
}
a) Science 80
b) Science 93
c) English 80
d) English 93
Answer: a)
Explanation:
r is an array variable of structure result type. The first print statement will print subject
value of the second array item. Similarly, the second print statement will print mark value of
the third array element. Hence, the correct option is a).
10
Question 11
Consider the code segment below. [MCQ, Marks 2]
#include <stdio.h>
__________________________ // LINE-1
void caller(char *msg, F_PTR fp) {
fp(msg);
}
int main() {
caller("Hello", &teller1);
caller("Hi", &teller2);
caller("Good Morning", &teller3);
return 0;
}
Identify the correct option to fill in the blank at LINE-1, such that the output is:
teller1: Hello
teller2: Hi
teller3: Good Morning
c) void *F PTR(char*);
Answer: b)
Explanation:
Since F PTR is the name of the function pointer, we need to define it with typedef. Thus, the
correct option is b).
11
Question 12
Consider the code segment below. [MSQ, Marks 2]
#include <stdio.h>
int main() {
int array[] = {10, 20, 30, 40, 50};
int *ip, i;
return 0;
}
Identify the correct option/s to fill in the blank at LINE-1, such that the output is:
50 40 30 20 10
a) -i[ip]
b) ip[-i]
c) -ip[i]
d) (-i)[ip]
Answer: b), d)
Explanation:
-i[ip] is equivalent to -*(i + ip), which prints -50 followed by 4 garbage values. So it is
wrong option.
ip[-i] is equivalent to *(ip - i), which prints 50 40 30 20 10.
-ip[i] is equivalent to -*(i + ip), which prints -50 followed by 4 garbage values. So it is
wrong option.
(-i)[ip] is equivalent to *(-i + ip), which prints 50 40 30 20 10.
12
Question 13
Consider the code segment below. [MCQ, Marks 2]
Assume that the sizeof(int) = 4
#include <stdio.h>
union uData {
int a;
int b;
};
struct sData {
union uData c;
int d;
};
int main() {
struct sData da = {10, 20};
return 0;
}
a) 8 10 10 20
b) 16 10 20 <garbage-value>
c) 16 10 <garbage-value> 20
d) 8 10 <garbage-value> 20
Answer: a)
Explanation:
sizeof(union uData) = 4, since the size of a union is same as the size of the largest element
of the union
Thus, the sizeof(da) = sizeof(struct sData) = sizeof(union uData) + sizeof(d) =
sizeof(union uData) + sizeof(int) = 8.
10 is intialized to the union data member. Hence, both union data member will hold 10 when
accessed. Hence, da.c.a = 10, da.c.b = 10 and da.d = 20.
13
Question 14
Consider the code segment below. [MCQ, Marks 2]
#include <stdio.h>
int main() {
int x = 8, y, z;
y = --x;
z = x--;
return 0;
}
a) 8 7 7
b) 8 7 6
c) 6 7 7
d) 6 7 6
Answer: c)
Explanation:
The first expression is y = --x; so, x becomes 7 because of pre-decrement operator and value
of y = 7. in the next step, the post decrement operator is applied on x. So, current value of
x is assigned to z (z = 7) then x decremented by 1 (x = 6). Hence, final values will be x=6,
y=7 and z=7.
14
Question 15
Consider the code segment below. [MCQ, Marks 2]
#include <stdio.h>
int main() {
int p = 5, q = 6;
return 0;
}
a) 35
b) 36
c) 41
Answer: d)
Explanation:
The operand of unary operator (increment / decrement) must be a variable, not a constant or
expression. In our case, unary increment operator is applied on expression p+q+5 which throws
a compilation error.
15
Programming in Modern C++: Assignment Week 1
Total Marks : 20
Question 1
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include<cmath>
int main(){
int n = 4;
_______________________________; //LINE-1
return 0;
}
Answer: a)
Explanation:
The cout function is defined under std namespace. We need to include std namespace before
using any cout statement or we need to call the cout statement as std::cout. The pow
function takes second parameter as 2 for squaring the first number. Hence, the correct option
is a).
1
Question 2
Consider the code segment given below. [MSQ, Marks 2]
#include <iostream>
#include<vector>
using namespace std;
int main(){
_________________ ; //LINE-1
arr.resize(10);
for (int i=0;i<10;i++)
arr[i] = i+1;
return 0;
}
Fill in the blank at LINE-1 such that the program will run successfully.
a) vector<int> arr
b) vector<int> arr(3)
c) vector<int> arr[3]
d) int arr[3]
Answer: a), b)
Explanation:
The resize function is not applied to C-style array. Hence, option d is incorrect.
Vector declared with size within brackets is a fixed size variable and hence cannot be resized.
So, option c) is incorrect.
Vector can be resized when it is declared as option a and b.
2
Question 3
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
#include<cstring>
using namespace std;
int main(){
string s = "programming in modern C++";
cout << s.size(); //LINE-1
cout << strlen(s); //LINE-2
cout << s.length(); //LINE-3
cout << strlen(s.c_str()); //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b)
Explanation:
The strlen function takes const char * type input to compute the length of the string. But,
LINE-2 is giving string type input to the strlen function which produces compilation error.
But LINE-4 converts the string type to c str type then that is passed to the strlen function.
This will not produce any compilation error. Function size and length works on string type
and correctly produces the length of the string.
Program intentionally made as MSQ
3
Question 4
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
int data[] = {50, 30, 40, 10, 20};
sort (&data[2], &data[5]);
for (int i = 0; i < 5; i++)
cout << data[i] << " ";
return 0;
}
a) 10 20 30 40 50
b) 10 30 40 50 20
c) 50 30 10 20 40
d) 50 10 20 30 40
Answer: c)
Explanation:
Since the call is sort(&data[2], &data[5]), it considers 3 elements of the array data[] from
the third element for sorting. Thus, it prints 50 30 10 20 40.
4
Question 5
Consider the code segment given below. [MSQ, Marks 2]
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string str1 = "Welcome ";
string str2 = "students";
_______________________; //LINE-1
cout << str1;
return 0;
}
Choose the appropriate option to fill in the blank at LINE-1, such that the output of the code
would be: Welcome students.
a) str1 += str2
b) strcat(str1, str2)
c) str1.append(str2)
d) str1.insert(str2)
Answer: a), c)
Explanation:
In C++, operator+= and append(·) concatenate the strings. Please note that strcat(·) is a
C function, and required the inclusion of cstring. The function insert(·) is used to insert a
string in another string at a given position.
5
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
int main(){
char str[10] = "COMPUTER";
stack<char> s1, s2;
int i;
for(i = 0; i < strlen(str)/3; i++)
s1.push(str[i]);
for(; i < strlen(str); i++)
s2.push(str[i]);
while (!s1.empty()) {
s2.push(s1.top()); s1.pop();
}
while (!s2.empty()) {
cout << s2.top(); s2.pop();
}
return 0;
}
a) COMPUTER
b) CORETUPM
c) UTERCOMP
d) COMPRETU
Answer: b)
Explanation:
The stack s1 stores {O, C}, and the stack s2 stores {R, E, T, U, P, M}. Then the elements of
s1 are also pushed into s2 as {C, O, R, E, T, U, P, M}. Thus, when we finally pop and print
the elements from s2, the output would be CORETUPM.
6
Question 7
Consider the code segment below. [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int iarr[5];
for(int i = 0; i < 5; i++)
*(iarr + i) = i * 2;
modify(iarr);
for (int i = 0; i < 5; ++i)
cout << *(iarr + i) << " ";
return 0;
}
a) 0 2 4 6 8
b) 0 2 6 8 4
c) 6 8 0 2 4
d) 2 4 6 8 0
Answer: b)
Explanation: rotate(first, middle, last) rotates the order of the elements in the range
[f irst, last], in such a way that the element pointed by middle becomes the new first element.
rotate(arr, arr + 3, arr + 5) makes the order as 6 8 0 2 4.
rotate(arr, arr + 2, arr + 4) makes the order as 0 2 6 8 4.
7
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int iarr[] = {10, 20, 50, 40, 10, 50};
rotate(&iarr[0], &iarr[2], &iarr[6]);
remove(&iarr[0], &iarr[6], 10); //LINE-1
for(int i = 0; i < 4; ++i)
cout << iarr[i] << " ";
return 0;
}
a) 40 10 10 20
b) 50 40 50 20
c) 50 50 40 20
d) 40 10 40 20
Answer: b)
Explanation: After execution of rotate(&iarr[0], &iarr[2], &iarr[6]), the contents of
array becomes 50 40 10 50 10 20 .
The remove function removes all instances of 10 from the array. Hence, the resultant array
will be 50 40 50 20.
8
Question 9
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
a) 1
b) 0
c) -1
Answer: a)
Explanation:
As per the LINE-1, it will return 1 if the first string is lexicographically larger than the second
string which is TRUE in our case. Hence the program will print 1.
9
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
• at LINE-1 with stack declaration,
• at LINE-2 to push values into stack,
• at LINE-3 with appropriate statement
such that it will satisfy the given test cases. Marks: 3
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
int main() {
char str[20];
char ch;
cin >> str;
________________; //LINE-1
for(int i = 0; i < strlen(str); i+=2)
________________; //LINE-2
int len = s.size();
for(int i = 0; i < len; i++) {
ch = ____________; //LINE-3
cout << ch;
s.pop();
}
return 0;
}
Public 1
Input: computer
Output: eumc
Public 2
Input: programming
Output: gimrop
Private
Input: discussion
Output: osusd
Answer:
LINE-1: stack<char> s
LINE-2: s.push(str[i])
LINE-3: s.top()
Explanation:
As the stack has to work with char type. Hence at LINE-1, we need to declare it as
stack<char> s;. At LINE-2, the elements can be pushed at stack as s.push(str[i]);.
We need to print the top of the stack for which LINE-3 will be filled as s.top().
10
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include <iostream>
___________________ //LINE-1
using namespace std;
struct point{
int x, y;
};
int main() {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
point p1, p2;
p1.x = x1;
p1.y = y1;
p2.x = x2;
p2.y = y2;
cout << round(get_len(p1, p2));
return 0;
}
Public 1
Input: 4 3 6 9
Output: 6
Public 2
Input: 2 5 3 9
Output: 4
Private
Input: 1 6 4 8
Output: 4
Answer:
LINE-1: #include <cmath>
LINE-2: sqrt(pow((p1.x - p2.x),2) + pow((p1.y - p2.y),2))
Explanation:
The C library math.h can be included in C++ program as
#include <cmath>
11
At LINE-2, the formula to compute the euclidean distance between two points can be imple-
mented as:
sqrt(pow((p1.x - p2.x),2) + pow((p1.y - p2.y),2))
12
Question 3
Consider the following program. Fill in the blanks as per the instructions given below:
#include <iostream>
#include <algorithm>
using namespace std;
___________________________ { //LINE-1
return _________; //LINE-2
}
int main() {
std::string words[3], word;
for(int i = 0; i < 3; i++){
cin >> word;
words[i] = word;
}
sort(words, words + 3, max_str);
for (int i = 0; i < 3; i++)
cout << words[i] << " ";
return 0;
}
Public 1
Input: hello hi bye
Output: hi hello bye
Public 2
Input: soumen arup himadri
Output: soumen himadri arup
Private
Input: c c++ java
Output: java c++ c
Answer:
LINE-1: bool max str (string s1, string s2)
LINE-2: (s1 > s2)
Explanation:
At LINE-1, define function header as:
bool max str (string s1, string s2)
At LINE-2, define the return statement for sorting in descending order as:
return (s1 > s2);
13
Programming in Modern C++: Assignment Week 2
Total Marks : 20
Question 1
Consider the following program. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int add(int n1 = 0) { return n1; }
int add(int n1 = 0, int n2 = 0) { return n1 + n2 - 1;}
int add(int n1 = 0, char c1 = ’a’){ return n1 + c1 - 1; }
int add(int n1 = 0, int n2 = 0, int n3 = 0) { return n1 + n2 + n3 - 1; }
int main() {
int c = add(2, 5);
cout << c << endl;
return 0;
}
a) 6
b) 99
c) Compilation Error: default argument missing for "int add(int, int, int)"
Answer: d)
Explanation:
The call add(2, 5), can invoke both the following overloads of add function:
int add(int n1 = 0, int n2 = 0) { ... }
int add(int n1 = 0, int n2 = 0, int n3 = 0) { ... }
Thus, the call is ambiguous. Hence, the correct option is d.
1
Question 2
Consider the code segment given below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
#define Times(x, y) (x * y)
int main() {
int a = 4;
cout << Times(a + 3, 5) << endl;
return 0;
}
a) 35
b) 20
c) 19
d) 23
Answer: c)
Explanation:
In a macro call, the arguments get substituted blindly, and then evaluated. So, the evaluation
of the cout expression will be done as follows:
2
Question 3
Consider the following code segment. [MSQ, Marks 2]
#include<iostream>
#define X 1
using namespace std;
int main(){
int i;
const int i1 = 2;
const int i2 = i1; //LINE-1
i2 = X + 5; //LINE-2
i = i1; //LINE-3
i1 = 4+5; //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b), d)
Explanation:
const data can only be initialized/updated at the time of declaration. Hence, LINE-2 and
LINE-4 gives a compilation error.
3
Question 4
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int& func(int& i) { //LINE-1
return i = i+5;
}
int main() {
int x = 1, y = 2;
int& z = func(x);
cout << x << " " << z << " ";
func(x+1) = y;
cout << x << " " << z;
return 0;
}
a) 6 6 2 2
b) 7 7 3 3
c) 6 6 3 2
Answer: d)
Explanation:
The function func has non-const reference but we are passing (x+1) which is of constant
expression. Hence it generates compilation error.
4
Question 5
Consider the code segment. [MCQ, Marks 2]
#include<iostream>
using namespace std;
int main(){
const int a = 5;
int &b = a+1;
b = a*b;
cout << a << " " << b;
return 0;
}
a) 5 30
b) 30 25
c) 25 36
Answer: d)
Explanation:
A reference variable can be initialized with an expression if it is a constant reference. Hence,
it will give a compilation error.
5
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int main() {
int a = 2, *b;
*b = a; Undefined behaviour
const int *ptr = &a; // LINE-1
*ptr = *b; // LINE-2
cout << *ptr;
return 0;
}
a) LINE-1
b) LINE-2
d) No error
Answer: b)
Explanation:
The pointer ptr is of constant type but b is not a constant type pointer. Hence, assignment
of non-const pointer to a constant pointer is illegal which generates compilation error.
No!
6
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
struct complex{
int re, im;
void show(){ cout << re << " + i" << im; }
};
______________________________{ //LINE-1
c2.re = c1.re - c2.re;
c2.im = c1.im - c2.im;
return c2;
}
int main(){
struct complex c1={2,5},c2{3,-2};
struct complex t = c1 - c2;
t.show();
return 0;
}
Answer: a), c)
Explanation: The operator overload function is changing the value of the second parameter
within the function. So, the second parameter of the function should not be constant. Hence,
correct options are a) and c).
7
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
char fun(int a, char b){
char c = a+b;
return c;
}
char fun(char a, int b){
char c = a-b;
return c;
}
int main(){
cout << fun(100,10); //LINE-1
return 0;
}
a) n
b) Z
c) NULL
Answer: d)
Explanation: The calling of function fun(.) is ambiguous because it matches with both the
function prototype. Hence, the correct option is d).
8
Question 9
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
#define MAXVAL(X, Y) (X > Y ? X : Y)
inline int maxval(int x, int y){
return x > y ? x : y;
}
int main(){
int x1 = 3, x2 = 4;
cout << MAXVAL(++x1, ++x2) << " ";
cout << maxval(++x1, ++x2) << " ";
return 0;
}
a) 5 6
b) 6 6
c) 6 5
d) 6 7
Answer: d)
Explanation:
In macro call, the arguments get substituted blindly, and then evaluated. However, in inline
function call, the arguments get evaluated before those are passed to the function.
The call MAXVAL(++x1, ++x2) will be expanded as: (++x1 > ++x2 > ++x1 : ++x2) =¿ (4
> 5 > ++x1 : ++x2) => (++x2) => 6.
The call maxval(++x1, ++x2) => maxval(5, 7), will return 7.
9
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
#include <iostream>
using namespace std;
______________________ { // LINE-1
int r = b + a;
cout << r;
}
int main() {
int a, b;
cin >> a >> b;
if (b < 0)
print(a);
else
print(a,b);
return 0;
}
Public 1
Input: 2 3
Output: 5
Public 2
Input: 8 -2
Output: 8
Private
Input: 4 -4
Output: 4
Answer:
LINE-1: void print(int a, int b=0)
Explanation:
The function header should have two parameters. The second parameter should have the
default value 0. So, LINE-1 can be filled with
void print(int a, int b = 0)
10
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include <iostream>
using namespace std;
int Fun(__________) { // LINE-1
x = ____________; // LINE-2
return x;
}
int main() {
int x, y;
cin >> x;
y = Fun(x);
cout << x << " " << y;
return 0;
}
Public 1
Input: 4
Output: 16 16
Public 2
Input: 2
Output: 4 4
Private
Input: 5
Output: 25 25
Answer:
LINE-1: int &x
LINE-2: x * x
Explanation:
The function call is made with an argument which should not be constant. As the function is
called with a call-by-reference strategy, the actual parameter value will be changed within the
function. So, LINE-1 should be filled as int &x. The function gives a square value as output.
So LINE-2 should be filled as x*x.
11
Question 3
Consider the following program. Fill in the blanks as per the instructions given below:
#include <iostream>
using namespace std;
struct point {
int x, y;
};
________________________________ { //LINE-1
pt1.x += pt2.x;
pt1.y += pt2.y;
_______________; //LINE-2
}
int main() {
int a, b, c, d;
cin >> a >> b >> c >> d;
point p1 = {a, b};
point p2 = {c, d};
point np = p1 + p2;
cout << "(" << p1.x << ", " << p1.y << ")" << "(" << np.x << ", " << np.y << ")";
return 0;
}
Public 1
Input: 1 2 3 4
Output: (4, 6)(4, 6)
Public 2
Input: 2 4 6 8
Output: (8, 12)(8, 12)
Private
Input: 2 1 -2 -1
Output: (0, 0)(0, 0)
Answer:
LINE-1: point operator+(point &pt1, point &pt2)
LINE-2: return pt1
Explanation:
We need to overload the addition operator for the structure point. Also, we are changing
the values of the passing parameter and the changed value should be reflected in the actual
parameter. Hence, LINE-1 should be filled as
point operator+(point &pt1, point &pt2)
and the return statement should be
return pt1
12
Programming in Modern C++: Assignment Week 3
Total Marks : 20
Question 1
Consider the following program. [MCQ, Marks 2]
#include <iostream>
#include <string>
using namespace std;
class Sample {
string name;
public:
Sample(){
cout << "s" << " ";
}
Sample(string s): name(s) {
cout << name << " ";
}
};
int main() {
Sample s1; //LINE-1
Sample *s2 = new Sample("s2");
Sample *s3;
new Sample("s4");
return 0;
}
b) s s2 s s4
c) s s2 s4
d) s2 s4
Answer: c)
Explanation:
The statement Sample s1; is not an error, but it instantiates an object by calling default
1
constructor. Hence it prints s.
Statement Sample *s2 = new Sample("s2");, instantiate an object, and call parametrized
constructor. Hence it prints s2.
Statement Sample *s3;, just create a pointer, don’t instantiate an object.
Statement new Sample("s4");, creates a temporary object, and call the parametrized con-
structor. Hence prints s4.
Hence, the correct option is c).
2
Question 2
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int i = 0;
class myClass {
public:
myClass() { i += 1;}
~myClass() { i += 5; }
};
void f(){
myClass m1();
myClass m2;
}
int fun() {
i = 3;
f();
return i++;
}
int main() {
cout << fun() << " ";
cout << i << endl;
return 0;
}
a) 3 4
b) 15 16
c) 9 10
d) 4 5
Answer: c)
Explanation:
i is initialized to 0 (i = 0; executes before main() is called).
Then main() starts and calls fun() which sets i to 3 by i = 3;. The fun() calls the function
f(). In function f(), first myClass m1(); is called, which does not instantiate any object.
Hence, this statement does not change the value of i. The next statement calls class construc-
tor, which makes the value of i as 4. As the function f() returns, the destructor of local object
m2 will be called before return and i become 9. This 9 will be returned by fun(), and get
printed.
Further i value incremented to 10 after return (Since i++ is post incremented).
Finally, value of i is printed as 10.
Hence correct option is c).
3
Question 3
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Private_Data {
int x;
void f1() {
cout << "Within f1";
}
public:
int y;
void f2() {
cout << "Within f2";
}
};
int main() {
Private_Data t;
t.x = 1; // LINE-1
t.f1(); // LINE-2
t.y = 2; // LINE-3
t.f2(); // LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: a), b)
Explanation:
All the class members declared under public accessible inside and outside the class. The class
members declared as private can be accessed only by the public functions inside the class.
LINE-1 gives error as x is private member.
LINE-2 gives error as f1() is private member function.
LINE-3 is fine as y is public member.
LINE-4 is fine as function f2() is public member function.
4
Question 4
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class MyClass {
public:
MyClass(int i) { cout << i; }
MyClass(const MyClass &t) { cout << "2"; }
};
int main(){
MyClass *t1, *t2; //LINE-1
t1 = new MyClass(0); //LINE-2
t2 = new MyClass(*t1); //LINE-3
MyClass t3 = *t1; //LINE-4
MyClass t4 = *t2; //LINE-5
return 0;
}
a) 02020202
b) 0202
c) 0222
d) 0002
Answer: c)
Explanation:
At LINE-1, the statement MyClass *t1, *t2; declares two pointers. So no objects are in-
stantiated, hence the constructors are not called.
At LINE-2, the statement t1 = new MyClass(0); invokes the parameterized constructor.
Hence the output is 0.
At LINE-3, the statement t2 = new MyClass(*t1); invokes the copy constructor. Hence the
output is 2.
At LINE-4 and 5, the statements MyClass t3 = *t1; and MyClass t4 = *t2; invoke the
copy constructor. Hence the output will be 22.
So option c) is correct.
5
Question 5
Consider the code segment. [MSQ, Marks 2]
class Check {
// code...
};
int main() {
const Check c; // LINE-1
return 0;
}
Answer: c), d)
Explanation:
this pointer is always a constant. So for class Check, the type of this for Check c would be
Check * const.
In LINE-1, the object is a constant. So the type of the this pointer of a constant object (as
specified const Check) of class Check is:
const Check* const this; or Check const* const this;
6
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class Test{
public:
Test() { cout << "O" << endl; }
Test(int x=0) { cout << "K" << endl; }
};
int main(){
Test t1;
return 0;
}
a) O
b) K
c) OK
Answer: d)
Explanation:
The program contains an ambiguous definition of Test constructor, where the default con-
structor and parameterized constructor with default parameter make ambiguity in creating
objects. Hence, the program will give a compilation error.
7
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Point {
int x, y;
public:
Point(int _x, int _y) : x(_x), y(_y) { }
Point(Point &c) : x(c.x), y(c.y){ }
void change(Point *new_c) { this = new_c; }
void show() { cout << x << ", " << y << endl; }
};
int main() {
Point c1(10, 20);
Point c2(20, 50);
Point c3(c1);
c3.change(&c2);
c3.show();
return 0;
}
a) 10 20
b) 20 50
Answer: c)
Explanation: In the function change(&c2), the statement
this = new c;
attempts an assignment to this. Since this is a constant pointer (Point * const), it cannot
be changed and the error occurs during compilation.
8
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <string>
using namespace std;
class Data{
int _d = 0;
public:
int set_d(int d) const {
_d = d;
}
int get_d() const {
return _d;
}
};
int main(){
const Data obj;
obj.set_d(5);
cout<<obj.get_d();
return 0;
}
a) 0
b) 5
c) 6
Answer: d)
Explanation: As the set d() is a constant function, it cannot change the state of an object.
Hence, when we try to assign value to d it gives compiler error, i.e. option d).
9
Question 9
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class Print {
int x;
public:
Print(int _x): x(_x) { }
void display() { cout << _________ << " "; } //LINE-1
};
int main() {
Print i(1);
i.display();
return 0;
}
a) ++x
b) ++this->x
c) x++
d) ++this.x
Answer: a), b)
Explanation:
When the display(.) function is called, the value of x is 1. So, we need to increment x before
printing. It can be done using ++this->x or ++x.
10
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
• Complete the return statement at LINE-3 to calculate the manhattan distance between
two points,
#include<iostream>
#include<cmath>
using namespace std;
class Point{
const int x,y;
public:
Point(int _x=0, int _y=0) : ______________ {} //LINE-1
Point(const Point& p) : _________________ {} //LINE-2
double distance(Point p){
return ________________________; //LINE-3
}
void print(){ cout << "(" << x << "," << y << ")" << endl; }
};
int main(){
int x1,x2,y1,y2;
cin >> x1 >> y1 >> x2 >> y2;
Point p1(x1,y1), p2(x2,y2);
p1.print();
p2.print();
cout << "Distance: " << p1.distance(p2);
return 0;
}
Public 1
Input: 1 2 3 4
Output:
(1, 2)
(3, 4)
Distance: 4
Public 2
Input: 1 -1 2 -2
Output:
(1, -1)
(2, -2)
Distance: 2
11
Private
Input: 2 4 6 8
Output:
(2, 4)
(6, 8)
Distance: 8
Answer:
LINE-1: x( x), y( y)
LINE-2: x(p.x), y(p.y)
LINE-3: (abs(x-p.x) + abs(y-p.y))
Explanation:
The parameterized constructor at LINE-1 will be filled as x( x), y( y).
The copy constructor at LINE-2 will be filled as x(p.x), y(p.y).
The manhattan distance between two points can be calculated at LINE-3 as (abs(x-p.x) +
abs(y-p.y))
12
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include<iostream>
using namespace std;
class Array{
int *arr;
int size;
public:
Array(int n) : _________________________{} //LINE-1
~Array(){ _____________; } //LINE-2
void Enter(){
for(int i=0;i<size;i++)
cin >> arr[i];
}
void FindMin(){
int min = 999;
for(int i=0;i<size;i++){
if(min > arr[i])
min = arr[i];
}
cout << "Min: " << min;
}
};
int main(){
int n;
cin >> n;
Array a(n);
a.Enter();
a.FindMin();
return 0;
}
Public 1
Input: 4
1 3 5 8
Output: Min: 1
Public 2
Input: 3
7 3 9
Output: Min: 3
13
Private
Input: 5
3 6 4 7 9
Output: Min: 3
Answer:
LINE-1: arr(new int[n]), size(n)
LINE-2: delete[] arr
Explanation:
The parameterized constructor of the class should initialize the data members of the class.
Using the constructor, we need to allocate memory to the data member arr and initialize
size. So, LINE-1 needs to be filled as arr(new int[n]), size(n). The destructor should free
memory which is allocated dynamically to the data member arr. So, LINE-2 should be filled
as delete[] arr.
14
Question 3
Consider the following program. Fill in the blanks at LINE-1, LINE-2 and LINE-3 with
appropriate keywords such that it will satisfy the given test cases. Marks: 3
#include<iostream>
using namespace std;
class Student{
const int sid;
string sname;
________ int marks; //LINE-1
public:
Student(int a, string b, int c) : sid(a), sname(b), marks(c) {}
void updateMarks(int x) ________ { marks += x; } //LINE-2
void print() ________ { //LINE-3
cout << sid << " : " << sname << " : " << marks;
}
};
int main(){
string n;
int i, m, u;
cin >> i >> n >> m >> u;
const Student s1(i, n, m);
s1.updateMarks(u);
s1.print();
return 0;
}
Public 1
Input: 1 Raj 36 5
Output: 1 : Raj : 41
Public 2
Input: 2 Amal 48 20
Output: 2 : Amal : 68
Private
Input: 3 John 80 10
Output: 3 : John : 90
Answer:
LINE-1: mutable
LINE-2: const
LINE-3: const
Explanation:
The object of class Student is declared as constant. So, all functions of class Student should be
declared as const in order to access them using the constant object. So, LINE-2 and LINE-3
will be filled as const. The data member marks of constant object is being changed using
function updateMarks(). Hence, LINE-1 should be filled as mutable.
15
Programming in Modern C++: Assignment Week 4
Total Marks : 20
Question 1
Consider the following program. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class Student{
string name = "Raj";
public:
______________________________; //Line-1
};
void show(const Student &t){
cout << "Hello " << t.name ;
}
int main(){
Student t;
show(t);
return 0;
}
Fill in the blank at LINE-1 such that the program will print ”Hello Raj”.
Answer: b), d)
Explanation:
The global function show() is accessing a private member of the class Student. So, the function
has to be friend of class Student. So, correct options are b) and d).
1
Question 2
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class statC{
static double d=9.81;
public:
void display() { cout << d << endl; }
};
int main(){
statC s;
s.display();
return 0;
}
a) 9.81
b) 9
c) 0
Answer: d)
Explanation:
In-class initialization is not allowed for non-const static members. So it will give a compilation
error.
2
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class Test1{
int id;
public:
Test1(int x) : id(x) { cout << id << " "; }
~Test1() { cout << id << " "; }
void fun(){
static Test1 t2(5);
}
};
int main(){
Test1 t1(1);
t1.fun();
return 0;
}
a) 1 5 5 1
b) 1 5 1 5
c) 5 1 1 5
d) 5 1 5 1
Answer: b)
Explanation:
The lifetime of a static object will end only after the whole program execution. So, the
constructor of object t1 from the main function will be called first, which will print 1. After
that, constructor from function fun() will be called, which will print 5. Then main function
object will be destroyed. At last, the static object will be destroyed.
3
Question 4
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int data = 0;
namespace ns {
int data = 2;
}
int main() {
using namespace ns;
int data = 1;
cout << ::data << " " << data << " " << ns::data; // LINE-1
return 0;
}
a) 0 1 2
b) 1 0 2
c) 0 2 1
d) 2 1 0
Answer: a)
Explanation:
When there are multiple instances of the same variable, the local instance will get higher
priority. So, data will be printed as 1. To access global variables, we use ::data. For the
namespace variable, it is qualified by the namespace ns. So, cout statement at LINE-1 will
be printed as 0 1 2.
4
Question 5
Consider the code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Test {
static int X;
public:
static void print() {
cout << X;
}
_______________ update(int a){ //Line-1
X=a;
}
};
int Test::X = 10;
int main() {
Test::update(4);
Test::print();
return 0;
}
Fill in the blank at LINE-1 such that the program will print 4.
a) void static
b) void const
c) static void
d) void
Answer: a), c)
Explanation:
A function can be called using the class name only when it is static function. So, the function
update should be declared as static. Hence, correct options are a) and c).
5
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
int x=1;
namespace ns{
int x=5;
}
int main(){
__________________; //LINE-1
cout << x;
return 0;
}
b) using ns::x
c) using namespace ns
Answer: b)
Explanation:
The namespace variable x needs to be made available in order to print 5 as output. This can
be done by filling up in LINE-1 as using ns::x.
6
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class Test{
_______________ x; //LINE-1
public:
Test(int _x) : x(_x) {}
void setx(int a) const{
x = a;
}
void display() const{
cout << x << endl;
}
};
int main(){
const Test m(5);
m.setx(0);
m.display();
return 0;
}
a) mutable int
b) int mutable
c) const int
d) int
Answer: a), b)
Explanation: To change the value of a data member of a constant object, we need to declare
the data member as mutable. So, the syntax is mutable int or int mutable.
7
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
namespace name{
class myClass{
int a;
public:
myClass(int x) : a(x) {}
void print(){ cout << a; }
};
}
int main(){
___________________; //LINE-1
m.print();
return 0;
}
a) name::myClass m(5)
b) myClass m(5)
d) name.myClass m(5)
Answer: a)
Explanation: The class is declared under namespace name. So, correct declaration of an
object of class myClass will be name::myClass m(5).
8
Question 9
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class classA{
static int a;
public:
int get(){ return a; }
_____________________; //LINE-1
};
int classA::a = 0;
class classB{
int b;
public:
classB(int y) : b(y) {}
void print(){
classA::a = 4;
cout << b << " " << classA::a;
}
};
int main(){
classB t2(5);
t2.print();
return 0;
}
Answer: a)
Explanation:
Here, class classB is accessing a private static data member of class classA. This can only be
possible if class classB is a friend of class classA or classB::print() function is a friend of
class classA. But we can’t declare classB::print() as friend at LINE-1 because there is no
forward declaration of class classB. Hence, the correct option is a).
Intentionally made as MSQ
9
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
• Complete the function prototype at LINE-2 and LINE-3 with appropriate keywords
#include<iostream>
using namespace std;
class Employee{
const int id;
string name;
________ int salary; //LINE-1
public:
Employee(int a, string b, int c) : id(a), name(b), salary(c) {}
void updateSal(int x) ______{ salary += x; } //LINE-2
void print() ______{ cout << id << " : " << name << " : " << salary; } //LINE-3
};
int main(){
string n;
int i, m, u;
cin >> i >> n >> m >> u;
const Employee e1(i, n, m);
e1.updateSal(u);
e1.print();
return 0;
}
Public 1
Input: 1 Raj 10000 1000
Output: 1 : Raj : 11000
Public 2
Input: 2 Zakir 50000 5000
Output: 2 : Zakir : 55000
Private
Input: 3 Sam 1000 300
Output: 3 : Sam : 1300
Answer:
LINE-1: mutable
LINE-2: const
LINE-3: const
Explanation:
The object of class Employee is declared as constant. So, all functions of class Employee should
be declared as const in order to access them using the constant object. So, LINE-2 and LINE-3
10
will be filled as const. The data member salary of constant object is being changed using
function updateSal(). Hence, LINE-1 should be filled as mutable.
11
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
• at LINE-1 with appropriate forward declaration,
Public 1
Input: 3 4
Output: 12 -1
Public 2
Input: 2 7
Output: 14 -5
Private
Input: 8 4
Output: 32 4
12
Answer:
LINE-1: class B
LINE-2: friend class A
Explanation:
LINE-1 should be filled with forward declaration of class B because the class B is used in
class A. As, both functions of class A are accessing private member of class B, class A
should be a friend of class B. So, LINE-2 should be filled as friend class A.
13
Question 3
Consider the following program. Fill in the blanks at LINE-1, LINE-2 and LINE-3 with appro-
priate statements such that it will satisfy the given test cases. Marks:
3
#include<iostream>
using namespace std;
class Singleton{
int data;
__________________ *ins; //LINE-1
Singleton(int i) : data(i) {}
public:
int get(){ return data; }
_________________ createIns(int i){ //LINE-2
if(!ins)
ins = ___________________; //LINE-3
return ins;
}
~Singleton(){ cout << data; }
};
Singleton *Singleton::ins = 0;
void fun(int x){
Singleton *s = Singleton::createIns(x+5);
cout << s->get();
}
int main(){
int i, j;
cin >> i >> j;
Singleton *s = Singleton::createIns(i);
cout << s->get();
fun(j);
return 0;
}
Public 1
Input: 1 2
Output: 11
Public 2
Input: 2 3
Output: 22
Private
Input: 3 5
Output: 33
Answer:
LINE-1: static Singleton
LINE-2: static Singleton*
LINE-3: new Singleton(i)
14
Explanation:
The pointer variable ins needs to be declared as static so that the same instance can be used
by all objects. The function createIns() is returning ins variable which is of type static
Singleton*. Hence, LINE-2 should be filled as static Singleton*. We need to create an
object of type class Singleton which can be done at LINE-3 as new Singleton(i);
15
Programming in Modern C++: Assignment Week 5
Total Marks : 20
Question 1
Consider the following program. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class ClassA {
protected:
int i;
public:
ClassA(int _i) : i(_i) {}
void func() { cout << i << endl; }
};
class ClassB : public ClassA {
public:
ClassB(int _i) : ClassA(_i) {}
void func(int x) { cout << i * x << endl; }
};
int main(){
ClassB iA(5);
iA.func(); //LINE-1
return 0;
}
a) 5
b) 1
c) 0
Answer: d)
Explanation:
When we overload base class function in the derived class, the base class function will not be
available to call using derived class object. So, it will be compilation error at LINE-1.
1
Question 2
Consider the code segment given below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class base{
protected:
int t1;
};
class derived : public base{
public:
int t2;
int sum(){ return t1 + t2; }
};
int main(){
base b;
derived d;
b.t1 = 10; //LINE-1
d.t1 = 20; //LINE-2
d.t2 = 30; //LINE-3
cout << d.sum(); //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: a), b)
Explanation:
In public inheritance, protected members of base class, appear as protected members of derived
class. Hence, in LINE-2 the code d.t1 = 20; gives an error. Protected members cannot be
accessed outside the class. So, LINE-1 will give an error.
2
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class Base {
public:
void f() { cout<< "Base class"; }
};
class Derived : public Base {
public:
void f() { cout<<"Derived class"; };
};
main() {
Derived obj;
_______________; //LINE-1
return 0;
}
Fill in the blank at LINE-1 so that the program will print Base class.
a) Base.obj.f()
b) Base.obj::f()
c) obj.Base::f()
d) Base::obj.f()
Answer: c)
Explanation:
As the function f() needs to be called from the base class Base, the appropriate syntax for
the function call is obj.Base::f().
3
Question 4
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class square{
protected:
int w;
public:
square(int _w) : w(_w){}
int area(){ return w * w; }
};
class rectangle : public square{
int h;
public:
rectangle(int _w, int _h) : _____________ { } //LINE-1
int area(){ return w * h; }
};
int main(){
rectangle *s = new rectangle(2,4);
cout << s->area();
return 0;
}
a) square( w), h( h)
b) h( h), square( w)
c) w( w), h( h)
Answer: a), b)
Explanation:
The protected data member should be initialized from the derived class constructor. It can be
done using option a) and b).
4
Question 5
Consider the code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Base {
protected:
int t1;
public:
Base(int _t1) : t1(_t1) { }
};
class Derived : _____________ { //LINE-1
protected:
int t2;
public:
Derived(int _t1, int _t2) : Base(_t1), t2(_t2) { }
};
class ReDerived : private Derived {
public:
ReDerived(int _t1, int _t2) : Derived(_t1, _t2) { }
void print() { cout << t1 << " " << t2; }
};
int main() {
ReDerived d(10, 20);
d.print();
return 0;
}
Fill in the blank at LINE-1 so that the program will print 10 20.
a) private Base
b) protected Base
c) public Base
d) public ReDerived
Answer: b), c)
Explanation:
As ReDerived class is already a child class of Derived class, and hence option (d) is wrong.
If we use private inheritance (option (a)), then the data-member t1 becomes private in class
Derived. Hence, t1 can not be inherited in class ReDerived. So, option (a) is also wrong.
However, both options (b) and (c) are correct options.
5
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class A{
int x, y;
};
class B{
protected:
int z;
public:
void f(){ cout << "B::f()"; }
};
class C : public A, public B{
A obj1;
};
int main(){
cout << sizeof(C);
return 0;
}
a) 0
b) 12
c) 16
d) 20
Answer: d)
Explanation:
As the class C inherits both the classes A and B and also has a data-member A obj1;, the
sizeof(C) is calculated as follows:
sizeof(C) = sizeof(A) + sizeof(B) + sizeof(obj1) = 8 + 4 + 8 = 20
6
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class Base{
public:
void print() { cout << "Class Base" << endl; }
};
class Derived : private Base {
public:
Derived() { ________________ } //LINE-1
};
int main(){
Derived t1;
return 0;
}
Fill in the blank at LINE-1 so that the program will print Class Base.
a) Base::print();
b) Base::print;
c) Base.print();
d) (new Base)->print();
Answer: a), d)
Explanation: It can be seen that the print() function needs to be called from class Derived
constructor in order to print Class Base. So, it can be called using the class name or temporary
object. So, options a) and d) are correct.
7
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class A {
static int x1;
int x2 = 5;
public:
void fun1() { cout << "f1" << endl; }
};
class B : public A {
int d1 = 10;
};
int A::x1 = 0;
int main(){
B t1;
cout << sizeof(t1) << endl;
return 0;
}
a) 1
b) 4
c) 8
d) 12
Answer: c)
Explanation: static member doesn’t take part in inheritance. So, derived class will not inherit
base class data member x1. Only x2 will be inherited from base class. So, the size of object d
will be 8 bytes.
8
Question 9
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class B {
public:
void print() { cout << "B" << " "; }
};
class D : public B {
public:
void print() { cout << "D" << " "; }
};
int main(){
B *a1 = new D();
D *b1 = new D();
a1->print();
b1->print();
return 0;
}
a) B D
b) D B
c) B B
d) D D
Answer: a)
Explanation:
Invocation of a function depends on the type of the pointer. In our case, the first pointer if of
type B*, and the second one is of type A*. Therefore, the output will be B D.
9
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
• Complete the return statement at LINE-2 and LINE-3 to calculate the volume and surface
area of a cube,
#include <iostream>
using namespace std;
class Volume {
public:
double getValue(int a) { return (a * a * a); }
};
class SurfaceArea {
public:
double getValue(int a) { return 6 * a * a; }
};
class Cube : _________________________________ { //LINE-1
int _a;
public:
Cube(int a) : _a(a) { }
double getVolume() { return _________________; } //LINE-2
double getSurfaceArea() { return _________________; } //LINE-3
};
int main() {
int a;
cin >> a;
Cube c(a);
cout << c.getVolume() << ", " << c.getSurfaceArea();
return 0;
}
Public 1
Input: 4
Output: 64, 96
Public 2
Input: 3
Output: 27, 54
Private
Input: 5
Output: 125, 150
Answer:
Answer:
10
LINE-1: public Volume, public SurfaceArea
LINE-2: Volume::getValue( a)
LINE-3: SurfaceArea::getValue( a)
Explanation:
The class Cube must inherit from both Volume and SurfaceArea classes. So at LINE-1, we use
class Cube : public Volume, public SurfaceArea
Note that any of public, protected, or private inheritance will work in this case, classes may
be put in any order, and private inheritance may be implied by skipping the specifier/s for
inheritance. Hence, there are several fill-ups that will work as long as both classes Volume and
SurfaceArea are listed. The function getValue() is defined in both Volume and SurfaceArea
classes. To resolve the ambiguity, we need to use Volume::getValue( a) at LINE-2 to call
getValue() from class Volume and SurfaceArea::getValue( a) to call getValue() from
class SurfaceArea.
11
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include <iostream>
using namespace std;
class Vehicle{
string vehicleName;
int noOfWheels;
protected:
Vehicle(string s, int w) : vehicleName(s), noOfWheels(w) { }
public:
________ void vehicleDetails(const Vehicle&); //LINE-1
};
class Twowheeler : public Vehicle{
public:
Twowheeler(string n) : ____________ { } //LINE-2
};
class Fourwheeler : public Vehicle{
public:
Fourwheeler(string n) : ____________ { } //Line-3
};
void vehicleDetails(const Vehicle &v){
cout << v.vehicleName << ": ";
if(v.noOfWheels == 2)
cout << "Two Wheeler";
else if(v.noOfWheels == 4)
cout << "Four Wheeler";
}
int main(){
string s;
int n;
Vehicle *v;
cin >> s >> n;
if(n==2)
v = new Twowheeler(s);
else if(n==4)
v = new Fourwheeler(s);
vehicleDetails(*v);
return 0;
}
Public 1
Input: Bus 4
Output: Bus: Four Wheeler
12
Public 2
Input: Bike 2
Output: Bike: Two Wheeler
Private
Input: Truck 4
Output: Truck: Four Wheeler
Answer:
LINE-1: friend
LINE-2: Vehicle(n,2)
LINE-3: Vehicle(n,4)
Explanation:
The global function vehicleDetails needs access private members of class Vehicle. So, it
should be a friend function of class Vehicle. LINE-1 will be filled with friend.
From LINE-2, constructor of class Vehicle needs to be called with noOfWheels value as 2. It
can be done as Vehicle(n, 2).
In the similar way, LINE-3 will be filled as Vehicle(n, 4).
13
Question 3
Consider the following program. Fill in the blanks as per the instructions given below.
#include<iostream>
using namespace std;
class B1{
protected:
int b1;
public:
B1(int b) : b1(b){}
};
class B2{
protected:
int b2;
public:
B2(int b) : b2(b){}
};
class D : __________________________{ //LINE-1
int d;
public:
D(int x) : _________________________________{} //LINE-2
void show(){
cout << d << ", " << b1 << ", " << b2;
}
};
int main(){
int x;
cin >> x;
D t1(x);
t1.show();
return 0;
}
Public 1
Input: 1
Output: 1, 6, 11
Public 2
Input: 5
Output: 5, 10, 15
Private
Input: 10
Output: 10, 15, 20
14
Answer:
LINE-1: public B1, public B2
LINE-2: B1(x+5), B2(x+10), d(x)
Explanation:
The function show() of class D is accessing protected member of both class B1 and class B2.
This can be done when D class is inherited from class B1 and B2. So, LINE-1 will be filled as
public B1, public B2 or protected inheritance in any order.
As per the test cases, the constructor at LINE-2 needs to be filled as
B1(x+1), B2(x+2), d(x) or in any order.
15
Programming in Modern C++: Assignment Week 6
Total Marks : 20
Question 1
Consider the following program. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class Class1{
public:
void fun1() { cout << "C1" ; }
virtual void fun2() { cout << "C2" ; }
};
class Class2 : public Class1{
public:
void fun1() { cout << "C3" ; }
void fun2() { cout << "C4" ; }
};
int main(){
Class1 *t = new Class2();
t->fun1();
t->fun2();
return 0;
}
What will be the output?
a) C1C4
b) C2C4
c) C1C3
d) C2C3
Answer: a)
Explanation:
As fun1() is a non-virtual function at the base class, for the t->fun1() function call, static
binding is done. So, the function of the pointer type will be called.
As fun2() is a virtual function at the base class, for the t->fun2() function call, dynamic
binding is done. So, the function of the object type will be called.
1
Question 2
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class ClassA{
public:
ClassA() { cout<<"1"; }
~ClassA() { cout<<"2"; }
};
class ClassB : public ClassA{
public:
ClassB() { cout<<"3"; }
virtual ~ClassB() { cout<<"4"; }
};
class ClassC : public ClassB{
public:
ClassC() { cout<<"5"; }
~ClassC() { cout<<"6"; }
};
int main(){
ClassA *t1 = new ClassC();
delete t1;
return 0;
}
a) 135642
b) 1352
c) 13542
d) 13562
Answer: b)
Explanation:
When the object of class classC is created, it calls the constructor of class classC, which in
turn calls the constructor of class classB and classA respectively. So, it will print 1 3 5.
Whenever the object is deleted, it calls the destructor of class classA first. The destructor of
class classA is not virtual, so it will not call the child class destructor. So, the final result will
be 1352.
2
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class student {
string msg = "Hello ";
public:
string greet(string name) { return (msg + name); }
};
class teacher : public student {
string msg = "Hi ";
};
void print(student &ob, string name){ cout << ob.greet(name) << endl; } //LINE-1
int main() {
student s1;
teacher t1;
print(s1, "Ravi"); //LINE-2
print(t1, "Sir"); //LINE-3
return 0;
}
a) Hello Ravi
Hi Sir
b) Hello Ravi
Hello Sir
c) Hi Ravi
Hello Sir
d) Hi Ravi
Hi Sir
Answer: b)
Explanation:
At LINE-2, the function call print(s1, ”Ravi”); invokes greet() from class student. Hence, the
output is Hello Ravi.
At LINE-3, the function call print(t1, "Sir"); is valid as it involves upper casting. However,
as the base class is not virtual, it is a compile-time binding situation. Hence, at LINE-1, the
function call ob.greet(name) invokes greet() from class student. Hence, the output is Hello
Sir.
3
Question 4
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class A{
public:
virtual void f() = 0;
};
class B : public A{
double data1;
public:
void f(){ cout << "B "; }
};
class C : public B{
double data2;
public:
void f(){ cout << "C "; }
};
int main(){
cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C);
return 0;
}
a) 0 8 16
b) 8 16 24
c) 4 12 20
d) 8 16 16
Answer: b)
Explanation:
Each pure virtual class maintains a pointer. Hence, sizeof(A) = 8.
Class B inherits class A and, additionally, has a data-member of type double. Hence, sizeof(B)
= sizeof(A) + sizeof(double) = 8 + 8 = 16.
Class C inherits class B and additionally has a data-member of type double. Hence, sizeof(C)
= sizeof(B) + sizeof(double) = 16 + 8 = 24.
4
Question 5
Consider the code segment. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class A{
public:
virtual void f(){ cout << "A::f() "; }
void g(){ cout << "A::g() "; }
void h(){ cout << "A::h() "; }
};
class B : public A{
public:
void f(){ cout << "B::f() "; }
void g(){ cout << "B::g() "; }
void h(){ cout << "B::h() "; }
};
class C : public B{
public:
void f(){ cout << "C::f() "; }
void g(){ cout << "C::g() "; }
virtual void h(){ cout << "C::h() "; }
};
int main(){
C cb;
B &bb = cb;
bb.f();
bb.g();
bb.h();
return 0;
}
Answer: c)
Explanation:
In class B, the function f() is a virtual function. As bb refers to the object cb, the output will
be C::f() C::g() B::h().
5
Question 6
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class classA{
public:
virtual void f(){ cout << "A::f() "; }
};
class classB : public classA{
public:
void f(){ cout << "B::f() "; }
};
class classC : public classB{
public:
void f(){ cout << "C::f() "; }
};
int main(){
classC *t = new classC;
_______________; //LINE-1
return 0;
}
Fill in the blank at LINE-1 so that the program will print A::f().
a) t->f()
b) classA::t->f()
c) classA::f()
d) t->classA::f()
Answer: d)
Explanation:
As t is a pointer to the object of class classC, we can call f() from class classA as t->classA::f()
such that it will print A::f().
Intentionally made as MSQ
6
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Test {
public:
virtual void f() = 0;
};
void Test::f() { // Line 1
cout << "Pure virtual function";
}
int main() {
Test t; // Line 2
Test *p = new Test(); // Line 3
p->f(); // Line 4
return 0;
}
The given program will not be compiled. Identify the correct reasons.
Answer: b), c)
Explanation: a) Pure virtual function can have a body. Incorrect reason.
b) Abstract base class (Test) cannot be instantiated. Correct reason.
c) We cannot use a new operator for an abstract base class. Correct reason.
d) Null pointer is checked at the run-time only. Incorrect reason.
7
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class Base{
public:
virtual void fun() { }
};
class Derived : public Base{
public:
void fun(double i) { }
};
int main(){
Derived t1;
Base *t2 = new Derived();
t1.fun(); //Line-1
t1.fun(3.14); //Line-2
t2->fun(); //Line-3
t2->fun(9.81); //Line-4
return 0;
}
a) Line-1
b) Line-2
c) Line-3
d) Line-4
Answer: a), d)
Explanation: The function fun() of class Base is overloaded in class Derived. So, the base
class function becomes hidden for the derived class. So, Line-1 will give an error. On the
other hand, class Base doesn’t have fun(int) in its definition. So, Line-4 will give an error.
8
Question 9
Consider the code segment given below. [MCQ, Marks 2]
class Flower {
public:
virtual void Petals() = 0 { cout << "Flower"; }
};
class FlowerWColor : public Flower {
void Petals() { cout << "Flower with color"; }
};
class FlowerWOColor : public Flower {};
class Rose : public FlowerWColor {
public:
void Petals() { cout << "Rose Flower"; }
};
class Jasmine : public FlowerWOColor {
public:
void Petals() { cout << "Jasmine Flower"; }
};
class Sunflower : public FlowerWColor {
public:
void Petals() { cout << "Sunflower flower"; }
};
d) Flower
Answer: b)
Explanation:
An abstract base class contains at least one pure virtual function. Moreover, a class derived
from an abstract base class will also be abstract unless you override each pure virtual function
in the derived class with non-pure ones. So, option b) is the correct answer.
9
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
#include<iostream>
using namespace std;
class B{
public:
B(){ cout << "1 "; }
B(double n){ cout << n << " "; }
______________; //LINE-1
};
class D : public B{
public:
D(double n) : _________ //LINE-2
{ cout << n * 3 << " "; }
D(){ cout << "3 "; }
virtual ~D(){ cout << "4 "; }
};
B::~B(){ cout << "2 "; }
int main(){
int i;
cin >> i;
B *pt = new D(i);
delete pt;
return 0;
}
Public 1
Input: 4
Output: 4 12 4 2
Public 2
Input: 2
Output: 2 6 4 2
Private
Input: 5
Output: 5 15 4 2
Answer:
Answer:
LINE-1: virtual ∼B()
10
LINE-2: B(n)
Explanation:
At LINE-1, the destructor needs to be defined as a virtual destructor, so that if the derived
class object gets deleted, it will be called automatically. Hence, LINE-1 has to be filled with
virtual ∼B();. The initialization list required at LINE-2 is B(n).
11
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include<iostream>
using namespace std;
class Test{
public:
__________________________ //Line-1
};
class ReTest1 : public Test{
int d1;
public:
ReTest1(int n) : ________{ } //Line-2
void fun();
};
class ReTest2 : public Test{
int d2;
public:
ReTest2(int n) : _______{ } //Line-3
void fun(){
cout << d2 << " ";
}
};
void ReTest1::fun(){
cout << d1 << " ";
}
int main(){
int i;
cin>>i;
Test *t1 = new ReTest1(i);
Test *t2 = new ReTest2(i);
t1->fun();
t2->fun();
return 0;
}
Public 1
Input: 2
Output: 4 6
Public 2
Input: 3
Output: 6 9
12
Private
Input: 4
Output: 8 12
Answer:
LINE-1: virtual void fun() = 0;
LINE-2: d1(2*n)
LINE-3: d2(3*n)
Explanation:
We need to declare function fun() as pure virtual in the Test class so that we can call it using
the Test class pointer. So, Line-1 will be filled as virtual void fun() = 0;
Line-2 and Line-3 will be filled with d1(2*n) and d2(3*n) respectively in order to complete
constructor definition.
13
Question 3
Consider the following program. Fill in the blanks as per the instructions given below.
#include <iostream>
using namespace std;
class shape{
protected:
int a,b;
shape(int x, int y) : a(x), b(y) {}
public:
_____________________________ //LINE-1
};
class triangle : public shape{
public:
triangle(int x, int y) : shape(x,y){}
void Area();
void show(){
______________; //LINE-2
Area();
}
};
__________________{ //LINE-3
cout << a+b << " ";
}
void triangle::Area(){ cout << (0.5 * a * b); }
int main(){
int a, b;
cin >> a >> b;
shape *sp = new triangle(a, b);
sp->show();
return 0;
}
Public 1
Input: 1
Output: 1, 6, 11
Public 2
Input: 5
Output: 5, 10, 15
14
Private
Input: 10
Output: 10, 15, 20
Answer:
LINE-1: virtual void show() = 0;
LINE-2: shape::show()
LINE-3: void shape::show()
Explanation:
At LINE-2, the function show() from class shape must be called as shape::show().
At LINE-3, the header for show() function must be void shape::show().
The pure virtual function at LINE-1 must be declared as virtual void show() = 0;.
15
Programming in Modern C++: Assignment Week 7
Total Marks : 20
September 1, 2023
Question 1
Consider the following program. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class A{
public:
virtual void f() {}
void g() {}
};
class B : public A{
public:
void g() {}
virtual void h() {}
virtual void i();
};
class C : public B{
public:
void f() {}
virtual void h() {}
};
What will be the virtual function table (VFT) for the class C?
a) C::f(C* const)
C::h(C* const)
B::i(B* const)
b) A::f(A* const)
B::g(B* const)
C::h(C* const)
B::i(B* const)
c) A::f(A* const)
B::h(B* const)
C::i(C* const)
1
d) A::f(A* const)
B::g(B* const)
C::h(C* const)
C::i(C* const)
Answer: a)
Explanation:
All three functions except g are virtual in the class C. So, there will be three entries in the
virtual function table.
Now, function f() is overridden in class C. So, the entry for function f() in the virtual
function table of class C will be C::f(C* const).
The function h() is declared as virtual in class C. So, the entry for function h() in VFT of
class C will be C::h(C* const).
The function i() is declared as virtual in class B. But not overridden in C. So, the entry for
function i() in VFT of class C will be B::i(B* const).
2
Question 2
Consider the code segment given below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
int main() {
char c = ’Z’;
int i = 50;
char *cp = &c;
int *pd;
c = static_cast<char>(i); // LINE-1
i = static_cast<double>(c); // LINE-2
pd = static_cast<double*>(cp); // LINE-3
c = static_cast<char>(&c); // LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: c), d)
Explanation:
static cast cannot cast between two different pointer types. In LINE-3, int* is assigned to
char*. Hence, it is an error.
Using static cast, it is not possible to change a pointer type to a value type. In LINE-4,
char* is assigned to char which is not possible using static cast.
3
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
using namespace std;
double incr(double* ptr){
return (*ptr)++;
}
int main() {
double val = 3.14;
const double *ptr = &val;
val = incr(________________________); //LINE-1
cout << val;
return 0;
}
Fill in the blank at LINE-1 such that the program will print: 3.14.
a) const cast<double*>(ptr)
b) static cast<double*>(ptr)
c) dynamic cast<double*>(ptr)
d) reinterpret cast<double*>(ptr)
Answer: a)
Explanation:
The function incr() modifies the value of *ptr, but the previous value is returned as return-
by-value. But, in main() function, ptr is declared as const double *ptr;. Hence, the
constant-ness of *ptr has to be removed, which can be done using const cast. So, a) is the
correct option.
4
Question 4
Consider the code segment given below. [MCQ, Marks 2]
a) 1
b) 2
c) 3
d) 4
Answer: d)
Explanation:
The presence of a virtual function (either explicitly declared or inherited from a base class)
makes the class polymorphic. For such classes, we need a class-specific virtual function table
(VFT). All four classes, thus, will set up virtual function tables.
5
Question 5
Consider the code segment. [MSQ, Marks 2]
a) s2 = static cast<C2*>(s1);
b) s2 = dynamic cast<C2*>(s1);
c) s2 = const cast<C2*>(s1);
d) s2 = reinterpret cast<C2*>(s1);
Answer: d)
Explanation:
On each option, there is an attempt to cast from C1* to C2*, and these two classes are unrelated.
As we know, only reinterpret cast can be used to convert a pointer to an object of one type to
a pointer to another object of an unrelated type. Hence, only option d) is correct.
6
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <typeinfo>
using namespace std;
class Base { public: virtual ~Base(){}};
class Derived: public Base {};
int main() {
Base b; Derived d;
Derived *dp = &d;
Base *bp = dp;
Derived *dpp = (Derived*)dp;
cout << (typeid(dp).name() == typeid(bp).name());
cout << (typeid(*dp).name() == typeid(*bp).name());
cout << (typeid(bp).name() == typeid(dpp).name());
cout << (typeid(*bp).name() == typeid(*dpp).name());
cout << (typeid(*dp).name() == typeid(*dpp).name());
return 0;
}
a) 00011
b) 01001
c) 01011
d) 00110
Answer: c)
Explanation:
Type of dp is Derived* and type of bp is Base*. Thus, output is 0.
*dp and *bp point to the same object d, and it is a dynamic binding situation. Thus, both are
of type Derived, and output is 1.
Type of bp is Base* and type of dpp is Derived*. Thus, output is 0.
*bp and *dpp point to the same object d, and it is a dynamic binding situation. Thus, both
are of type Derived, and output is 1.
*dp and *dpp point to the same object d, and it is a dynamic binding situation. Thus, both
are of type Derived, and output is 1.
7
Question 7
Consider the code segment below. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class book{
string _title;
string _author;
string _publisher;
public:
book(string title, string author, string publisher)
: _title(title), _author(author), _publisher(publisher){}
void changePublisher(string new_publisher) const{
(______________)->_publisher = new_publisher; //LINE-1
}
void book_details() const{
cout << _title << ":" << _author << ":" << _publisher;
}
};
int main(){
const book b("Modern C++", "Partha Pratim Das", "IIT KGP");
b.changePublisher("IITM");
b.book_details();
return 0;
}
Fill in the blank at LINE-1 so that the program will print Modern C++:Partha Pratim Das:IITM
a) (const book)this
b) (book*)this
c) const cast<book*>(this)
d) static cast<book*>(this)
Answer: b), c)
Explanation: As object b is a constant object, to modify the data-member publisher first
the current object needs to be converted to a non-constant object. It can be done at LINE-1
either of the two ways: (book*)this
or
const cast<book*>(this)
8
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class Base{
public:
virtual void f(){
cout << "B::f() ";
}
};
class Derived : public Base{
public:
virtual void f(){
cout << "D::f() ";
}
};
int main() {
Base obA;
Derived obB;
Base& ra1 = static_cast<Base&>(obB); //LINE-1
ra1.f();
Derived& rb1 = static_cast<Derived&>(obA); //LINE-2
rb1.f();
Base& ra2 = dynamic_cast<Base&>(obB); //LINE-3
ra2.f();
Derived& rb2 = dynamic_cast<Derived&>(obA); //LINE-4
rb2.f();
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: d)
Explanation: The statement at LINE-1 is having upper-casting, which may be done using
static cast. Hence, ra1.f(); prints D::f().
The statement at LINE-2, is having down-casting, which may be done using static cast. Hence,
rb1.f(); prints B::f().
The statement at LINE-3, is having upper-casting, which may be done using dynamic cast.
Hence, ra2.f(); prints D::f().
The statement at LINE-4, is having down-casting, which cannot be done using dynamic cast.
Hence, it generates a run time error.
9
Question 9
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class B{ public: virtual ~B(){} };
class D : public B{};
class DD : public B{};
int main(){
B objA;
D objB;
B* pA = dynamic_cast<B*>(&objB); //LINE-1
pA == NULL ? cout << "10 " : cout << "11 ";
D* pB = dynamic_cast<D*>(pA); //LINE-2
pB == NULL ? cout << "20 " : cout << "21 ";
DD* pC = dynamic_cast<DD*>(new B); //LINE-3
pC == NULL ? cout << "30 " : cout << "31 ";
pC = dynamic_cast<DD*>(&objB); //LINE-4
pC == NULL ? cout << "40 " : cout << "41 ";
return 0;
}
a) 11 21 31 40
b) 11 21 30 40
c) 11 20 31 40
d) 11 21 31 41
Answer: b)
Explanation:
The type-casting at LINE-1 is valid as it is an upper-casting.
At LINE-2, though it is a down-casting, it is allowed as the pointer pB points to the same type
of object (which of type D).
At LINE-3, the down-casting is invalid as the pointer pC points to the parent type of object
(which is of type B). At LINE-4, the casting is also invalid as the pointer pC points to an object
(which is of type D) that is neither of its base type or derived type.
10
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
#include<iostream>
#include<cctype>
using namespace std;
class Char{
char ch;
public:
______________ : ch(tolower(_ch)){} //LINE-1
__________________{ return ch; } //LINE-2
_______________{ return ch - ’a’ + 1; } //LINE-3
};
int main(){
char c;
cin >> c;
Char cb = c;
cout << (char)cb << ": position is " << int(cb);
return 0;
}
Public 1
Input: c
Output: c: position is 3
Public 2
Input: G
Output: g: position is 7
Private
Input: A
Output: a: position is 1
Answer:
Answer:
LINE-1: Char(char ch)
LINE-2: operator char()
LINE-3: operator int()
Explanation:
The statement Char cb = c; requires casting from char to class Char, which is implemented
by the constructor as: Char(char ch)
The statement (char)cb requires a casting operator from class Char to char which may be
done by function: operator char()
11
The statement int(cb) requires a casting operator from class Char to int which may be
done by function: operator int()
12
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
#include<iostream>
#include<cstring>
#include<malloc.h>
using namespace std;
class String{
char* _str;
public:
________________ : _str(str){} //LINE-1
___________________{ //LINE-2
char* t_str = (char*)malloc(sizeof(_str) + 7);
strcpy(t_str, "Coding is ");
strcat(t_str, _str);
return t_str;
}
};
int main(){
char s[20];
cin >> s;
String st = static_cast<String>(s);
cout << static_cast<char*>(st);
return 0;
}
Public 1
Input: fun
Output: Coding is fun
Public 2
Input: easy
Output: Coding is easy
Private
Input: logical
Output: Coding is logical
Answer:
LINE-1: String(char* str)
LINE-2: operator char*()
Explanation:
The constructor at LINE-1 can be defined as String(char* str). In LINE-2, char* casting
operator is overloaded. It can be done as operator char*().
13
Question 3
Consider the following program. Fill in the blanks as per the instructions given below:
#include<iostream>
using namespace std;
class ClassA{
int a = 10;
public:
void display(){
cout << a << " ";
}
};
class ClassB{
int b = 20;
public:
void display(){
cout << b;
}
________________(int x){ //LINE-1
b = b + x;
}
};
void fun(const ClassA &t, int x){
ClassA &u = ___________________(t); //LINE-2
u.display();
ClassB &v = _______________________(u); //LINE-3
v = x;
v.display();
}
int main(){
ClassA t1;
int a;
cin >> a;
fun(t1,a);
return 0;
}
Public 1
Input: 5
Output: 10 15
Public 2
Input: 3
Output: 10 13
14
Private
Input: 10
Output: 10 20
Answer:
LINE-1: void operator=
LINE-2: const cast<ClassA&>
LINE-3: reinterpret cast<ClassB&>
Explanation:
As per the function fun(), we need to overload operator equal to for the class ClassB at LINE-1
so that the assignment v = x will be valid. It can be done as operator=(int x).
To call a non constant function display(.) using a const object reference u, we need to cast
the reference to a non-const reference. So, LINE-2 will be filled as const cast<ClassA&>.
Casting between two unrelated classes at LINE-3 can be done as reinterpret cast<ClassB&>.
15
Programming in Modern C++: Assignment Week 8
Total Marks : 20
September 6, 2023
Question 1
Consider the following program. [MCQ, Marks 2]
#include<iostream>
class AEx{};
class BEx : public AEx{};
class CEx : public BEx{};
void evalEx(int i){
if(i == 0)
throw CEx();
else if(i < 0)
throw BEx();
else
throw AEx();
}
int main(){
try{
evalEx(-5);
evalEx(5);
evalEx(0);
}
catch(int& i){ //LINE-1
std::cout << "int";
}
catch(...){ //LINE-2
std::cout << "all";
}
catch(BEx& e){ //LINE-3
std::cout << "BEx" << " ";
}
catch(AEx& e){ //LINE-4
std::cout << "BEx" << " ";
}
1
catch(CEx& e){ //LINE-5
std::cout << "CEx" << ", ";
}
return 0;
}
a) all
b) BEx
c) Error at LINE-1
d) Error at LINE-2
Answer: d)
Explanation:
It is an error since ‘...’ handler must be the last handler for its try block.
2
Question 2
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
namespace Exceptions{
class AEx{};
class BEx : public AEx{};
class CEx : public BEx{};
}
void evalEx(){
try{
throw Exceptions::CEx();
throw Exceptions::BEx();
throw Exceptions::AEx();
}catch(Exceptions::BEx& e){ //LINE-1
std::cout << "BEx" << " ";
throw;
}
catch(Exceptions::AEx& e){ //LINE-2
std::cout << "BEx" << " ";
}
catch(Exceptions::CEx& e){ //LINE-3
std::cout << "CEx" << ", ";
throw 10;
}
}
int main(){
try{
evalEx();
}catch(int& i){ //LINE-4
std::cout << "int";
}
catch(...){ //LINE-5
std::cout << "all";
}
return 0;
}
What will be the output?
a) CEx int
b) BEx all
c) BEx BEx all
d) AEx CEx int
Answer: b)
Explanation:
The function evalEx() thorws the exception of type Exceptions::CEx which will be caught
at LINE-1 (since it is of base class type). This catch block prints BEx, and then re-throws the
same exception, which will be caught at LINE-5 in main. Therefore it prints all.
Hence, the correct option is b).
3
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include<iostream>
class AEx{ public: virtual void printEx() { std::cout << "AEx" << " "; } };
class BEx : public AEx{ public: void printEx() { std::cout << "BEx" << " "; } };
class CEx : public BEx{ public: void printEx() { std::cout << "CEx" << " "; } };
void evalEx(int i){
try{
if(i == 0)
throw CEx();
else if(i < 0)
throw BEx();
else
throw AEx();
}
catch(BEx& e){ //LINE-1
e.printEx();
}
catch(AEx& e){ //LINE-2
e.printEx();
}
catch(CEx& e){ //LINE-3
e.printEx();
}
catch(...){ //LINE-4
std::cout << "all";
}
}
int main(){
evalEx(-5);
evalEx(5);
evalEx(0);
return 0;
}
Answer: a)
Explanation:
Since printEx is a virtual function due to dynamic binding in all the catch blocks, printEx
will bind to its exact derive type. Therefore, the correct option is a).
4
Question 4
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
void evalEx(int i) {
i == 0 ? throw "zero" : throw i;
}
int main() {
try {
// statement-1
}
catch (int& e) {
std::cout << "int" << " ";
}
catch (float& e){
std::cout << "float" << " ";
}
catch (double& e){
std::cout << "duoble" << " ";
}
catch (const char* e) {
std::cout << "cstring" << " ";
}
catch (...) {
std::cout << "unknown" << " ";
}
return 0;
}
What will be the outputs in consecutive two runs if statement-1 is replaced by (i) evalEx(8.5);
and (ii)evalEx(0); respectively?
Answer: a)
Explanation:
For the call evalEx(8.5), the double value is type cast to int. Thus, when the exception of
int type is forwarded to the main, it would be caught by catch(int i){ ... }.
For the call evalEx(0), the exception type is const char* type. Thus, when the exception is
forwarded to the main, it would be caught by catch(const char* e){ ... }.
5
Question 5
Consider the code segment given below. [MCQ, Marks 2]
#include<iostream>
_______________________________________ //LINE-1
class Mapping{
private:
T1 x;
T2 y;
public:
Mapping(T1 x_, T2 y_){
x = x_;
y = y_;
}
void show(){
std::cout << x << " -> " << y << std::endl;
}
};
int main(){
Mapping<char, double> p0(’X’, 4.5);
Mapping<char> p1(65, 66);
Mapping<> p2(65, 66);
p0.show();
p1.show();
p2.show();
return 0;
}
Fill in the blank at LINE-1 such that the output of the program is:
X -> 4.5
A -> B
65 -> B
Answer: b)
Explanation:
From the output, it can be concluded that the default type of T1 is int and T2 is char. Thus,
option b) is correct.
6
Question 6
Consider the code segment given below. [MSQ, Marks 2]
#include<iostream>
template<class T>
T add(const T& a, const T& b) {
return a + b;
}
int main() {
std::cout << ________________; //LINE-1
return 0;
}
Which of the following statement/s used to fill in the blank at LINE-1 that results in compiler
error?
a) add(10, 20)
b) add(10, 20.5)
c) add(10.5, 20.5)
d) add(10.5f, 20.5)
Answer: b), d)
Explanation:
In option a), both the parameters are of type int, so T would be instantiated to int.
In option c), both the parameters are of type double, so T would be instantiated to double.
In option b), the first parameter is of type int and the second parameter is of type double,
so instantiation of T is ambiguous.
In option d), the first parameter is of type float and the second parameter is of type double,
so instantiation of T is ambiguous.
7
Question 7
Consider the code segment below. [MCQ, Marks 2]
#include <iostream>
int main() {
int arr[] = { 18, 30, 35, 22 };
int n = sizeof(arr) / sizeof(arr[0]);
genericPrint<int, n>(arr, n) << std::endl; //LINE-1
return 0;
}
a) 18 30 35
b) 18 30 35 22
c) 18 30 35 22 <garbage-value>
Answer: d)
Explanation: In a template declaration, any non-type parameter is a constant. Therefore,
at LINE-1, the value of n is not usable in the constant expression.
8
Question 8
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
struct cmp {
bool operator()(std::string s1, std::string s2) {
return (s1.length() < s2.length()) ;
}
};
int main(){
std::vector<std::string> sVec{"deer", "cat", "rabbit", "sheep"};
std::sort(sVec.begin(), sVec.end(), cmp());
for(int i = 0; i < sVec.size(); i++)
std::cout << sVec[i] << " ";
return 0;
}
Answer: c)
Explanation: Since the functor sort the strings of a given array in the ascending order of
their length, the correct option is c).
9
Question 9
Consider the following class definition in C++11. [MCQ, Marks 2]
class Notification{
public:
void alert(const char *msg) {
std::cout << msg << std::endl;
}
};
Identify the appropriate function pointer declaration that can point to the function alert
belongs to the class Notification as fp = &Notification::alert;.
Answer: d)
Explanation:
The appropriate syntax to declaration a function pointer to the member function alert of
class Notification is option d).
10
Programming Questions
Question 1
Consider the following program. Fill in the blanks as per the instructions given below:
• Fill in the blank at LINE-1 and LINE-2 with appropriate statements for class template
specialization.
#include<iostream>
#include<cstring>
#include<cstdlib>
template<typename T>
class Manipulator{
T val;
public:
Manipulator(T _val = 0) : val(_val) { }
T deduct(int d){
T t = val - d;
return t;
}
};
_______________________________ //LINE-1
_____________________________ { //LINE-2
char* val;
public:
Manipulator(const char* _val = 0) : ________________ { } //LINE-3
char* deduct(int d){
char* buf = (char*)malloc(strlen(val) - d + 1);
int i;
for(i = 0; i < strlen(val) - d; i++)
buf[i] = val[i];
buf[i] = ’\0’;
return buf;
}
};
int main(){
int a;
std::cin >> a;;
Manipulator<float> f = 100.45;
Manipulator<const char*> s("programming");
std::cout << f.deduct(a) << ", ";
std::cout << s.deduct(a);
return 0;
}
11
Public 1
Input: 3
Output: 97.45, programm
Public 2
Input: 5
Output: 95.45, progra
Private
Input: 10
Output: 90.45, p
Answer:
LINE-1: template<>
LINE-2: class Manipulator<const char*>
LINE-3: val(strdup( val))
Explanation:
For specialized class template declaration (for cstring), LINE-1 should be filled as template<>,
and LINE-2 should be filled class Manipulator<const char*>.
At LINE-3, the initializer for the given constructor can be written as val(strdup( val)).
12
Question 2
Consider the following program. Fill in the blanks as per the instructions given below.
• Fill in the blank at LINE-1 with appropriate template declaration for class DataSet.
• Fill in the blank at LINE-3 with appropriate parameter / parameters for function operator=.
#include <iostream>
_______________________________ // LINE-1
class DataSet {
private:
_______________; // LINE-2
int i;
public:
DataSet() : i(-1) { }
void operator=(__________){ // LINE-3
arr[++i] = data;
}
void print() {
for (int j = N - 1; j >= 0; j--)
std::cout << arr[j] << " ";
}
};
int main() {
const int n = 3;
DataSet<char, n> ds1;
for (int i = 0; i < n; i++) {
char j;
std::cin >> j;
ds1 = j;
}
DataSet<int, n> ds2;
for (int i = 0; i < n; i++) {
int j;
std::cin >> j;
ds2 = j;
}
ds1.print();
ds2.print();
return 0;
}
Public 1
Input:
a b c
1 2 3
Output: c b a 3 2 1
13
Public 2
Input:
x y z
10 20 30
Output: z y x 30 20 10
Private
Input:
p q r
6 5 4
Output: r q p 4 5 6
Answer:
LINE-1: template<typename T, int N>
LINE-2: T arr[N]
LINE-3: T& data
Explanation:
We have to declare a generic type in LINE-1 which will be used to declare an array arr. The
generic type will be template<typename T, int N>. We will declare the array arr with that
generic type at LINE-2 as T arr[N]. The parameter to be passed in operator function will be
T& data.
14
Question 3
Consider the following program. Fill in the blanks as per the instructions given below:
• Fill in the blank at LINE-1 with appropriate constructor for structure Stat.
• Fill in the blank at LINE-2 with appropriate header declaration for functor.
#include <iostream>
struct Stat {
int s;
____________________________________ //LINE-1
___________________________________ { //LINE-2
for(int i = 0; i < n; i++)
s += arr[i];
double a = (double)s / n;
____________________; //LINE-3
}
};
int main(){
int a, b, c[10];
std::cin >> a;
for(int i = 0; i < a; i++){
std::cin >> b;
c[i] = b;
}
int sum = 0;
Stat st(sum);
double avg = st(c, a);
std::cout << st.s << " " << avg;
return 0;
}
Public 1
Input: 4 10 20 30 40
Output: 100 25
Public 2
Input: 6 1 2 3 4 5 6
Output: 21 3.5
Private
Input: 5 10 -5 6 -9 1
Output: 3 0.6
15
Answer:
LINE-1: Stat(int& s) : s( s) { }
or
LINE-1: Stat(int s) : s( s) { }
LINE-2: double operator()(int arr[], int n)
LINE-3: return a
Explanation:
At LINE-1, the parameterized constructor with one parameter can be defined as:
Stat(int& s) : s( s) { }
or
Stat(int s) : s( s) { }
Please note that any other variable can also be used a formal parameter to the constructor.
At LINE-2, for defining the function header is defined as:
double operator()(int arr[], int n)
At LINE-3, the return statement can be written as:
return a
16
Programming in Modern C++: Assignment Week 9
Total Marks : 20
Question 1
Consider the following program. [MCQ, Marks 2]
#include<cstdio>
int main(){
int i = 65;
std::printf(__________________, i, i, i, i); //LINE-1
return 0;
}
Identify the correct option to fill in the blank at LINE-1 such that the output becomes 65 41
101 A.
a) "%d %o %x %c"
b) "%d %x %o %c"
Answer: b)
Explanation:
To print the value of i in decimal format, we use %d.
To print the value of i in hexadecimal format, we use %x.
To print the value of i in octal format, we use %o.
To print the value of i in char format, we use %c.
1
Question 2
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <iomanip>
int main () {
std::cout << std::setprecision(6) << std::setfill('0');
std::cout << std::setw(8) << (double)10/3;
return 0;
}
a) 3.333333
b) 03.33333
c) 000003.33333333
d) 03.333333
Answer: b)
Explanation:
10/3.0 = 3.3333...
setprecision(6) makes it to 3.33333
setfill(’0’) and setw(8) make it to 03.33333
Hence, the correct option is b).
2
Question 3
Consider fp as a file pointer to a existing file, and the file is open in readonly mode. Match
the appropriate descriptions about the fseek function calls. [MCQ, Marks 2]
Function calls Descriptions
1. fseek(fp, 100, SEEK SET) A. Move the file pointer to the end of the file
2. fseek(fp, -100, SEEK CUR) B. Move the file pointer forward from the beginning
of the file by 100 characters
3. fseek(fp, 0, SEEK END) C. Move the file pointer backwards from the current position
in the file by 100 characters
4. fseek(fp, -100, SEEK END) D. Move the file pointer backwards from the end
of the file by 100 characters.
Answer: d)
Explanation:
• fseek(fp, 100, SEEK SET) move the file pointer forward from the beginning of the file
by 100 positions.
• fseek(fp, -100, SEEK CUR) moves the file pointer backwards from the current position
in the file by 100 positions
• fseek(fp, 0, SEEK END) moves the file pointer to the end of the file
• fseek(fp, -100, SEEK END) moves the file pointer backwards from the end of the file
by 100 positions
3
Question 4
Consider the following code segment. [MCQ, Marks 2]
#include<cstdio>
int main(){
FILE *infp;
if((infp = std::fopen("myfile.txt", "r")) == NULL)
return -1;
int c, n = 0;
while((c = std::fgetc(infp)) != EOF)
if(c == '\n' || c == ' ') //LINE-1
n++;
std::printf("%d", n);
fclose(infp);
return 0;
}
Answer: b)
Explanation:
It increment n because (1) it counts on each blank space, (2) it counts on each newline, and
(3) it counts on end of line. Therefore, it prints the number of words in file myfile.txt.
4
Question 5
Consider the code given below to print all the lines from in.txt. [MCQ, Marks 2]
#include <iostream>
#include <fstream>
#include <string>
int main () {
std::ifstream infile("myfile.txt");
std::string line;
if (____________________) { //LINE-1
std::cout << "Unable to open file";
}
else{
while (std::getline(infile, line))
std::cout << line << std::endl;
infile.close();
}
return 0;
}
Identify the appropriate option to fill in the blank at LINE-1 such that it checks if the file does
not exist.
a) infile.is open()
b) !infile.is open()
c) !infile.open()
d) fopen(infile) == NULL
Answer: b)
Explanation:
Since the program attempts to read from the file, if the file exists or not can be verified by
is open() function. Thus, the correct option is b).
5
Question 6
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
#include <list>
#include <numeric>
class purchase{
public:
purchase(int itm_no, double pri, int qty) : itm_no_(itm_no), pri_(pri),
qty_(qty){}
double get_pri(){ return pri_; }
int get_qty(){ return qty_; }
private:
int itm_no_;
double pri_;
int qty_;
};
struct compute_price{
double operator()(double d, purchase p) {
return d + p.get_pri() * p.get_qty();
}
};
int main(){
std::list<purchase> li { purchase(101, 500.0, 10), purchase(102, 400.0, 5),
purchase(102, 600.0, 5)};
compute_price cp;
double cost = compute_total(li, cp);
std::cout << cost;
return 0;
}
Which of the following statement can be used to fill in the blank at LINE-1 that the output
becomes 10000.
a) li.begin(), li.end()
b) li.begin(), li.end(), cp
c) li.begin(), li.end(), 0.0, cp
d) li.begin(), li.end(), 0.0
Answer: c)
Explanation:
The arguments of std::accumulate function are starting and ending of list, the value to
initialize the sum, and function (or functor) to be applied. Therefore, c) is the correct option.
6
Question 7
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
#include <algorithm>
#include <list>
int main() {
char ca[] { 't', 'r', 'i', 'a', 'n', 'g', 'l', 'e' };
int len = sizeof(ca) / sizeof(*ca);
std::list<char> lc(len);
____________________________________________; //LINE-1
Identify the appropriate call to copy function to fill in the blank at LINE-1 such that it prints
angle as output.
Answer: b), d)
Explanation:
The syntax of copy function is as follows:
7
Question 8
Consider the following code segment which computes inner product of the elements of list and
vector. [MSQ, Marks 2]
#include <iostream>
#include <list>
#include <vector>
#include <numeric>
struct add{
int operator()(int i, int j){ return i + j; }
};
struct multi{
int operator()(int i, int j){ return i * j; }
};
int main() {
std::list<int> li { 4, 5, 6 };
std::vector<int> vi { 7, 8, 9 };
Identify the appropriate call/calls to inner product function to fill in the blank at LINE-1
such that it prints 122 as output.
Answer: b), c)
Explanation:
The code by inner product function is:
template<class In, class In2, class T, class BinOp, class BinOp2 >
T inner_product(In first, In last, In2 first2, T init, BinOp op, BinOp2 op2) {
while(first!=last) {
init = op(init, op2(*first, *first2));
++first; ++first2;
}
return init;
}
8
Question 9
Consider the code segment below. [MCQ, Marks 2]
#include<iostream>
#include <algorithm>
#include<vector>
class product{
public:
product(int prod_num, std::string prod_nam) :
prod_num_(prod_num), prod_nam_(prod_nam){}
int get_prod_num(){ return prod_num_; }
std::string get_prod_nam(){ return prod_nam_; }
private:
int prod_num_;
std::string prod_nam_;
};
struct compare{
bool operator()(product p1, product p2){
if(p1.get_prod_nam() == p2.get_prod_nam()){
if(p1.get_prod_num() > p2.get_prod_num()){
return true;
}
else{
return false;
}
}
else if(p1.get_prod_nam() > p2.get_prod_nam())
return true;
else
return false;
}
};
int main() {
std::vector<product> prod { product(103, "Pen"), product(102, "Pencil"),
product(106, "scale"), product(104, "Pen"),
product(105, "sharpener") };
sort(prod.begin(), prod.end(), compare());
for(std::vector<product>::iterator it = prod.begin(); it < prod.end(); it++)
std::cout << it->get_prod_num() << " : " << it->get_prod_nam() << std::endl;
return 0;
}
What will be the output?
a) 105 : sharpener
106 : scale
102 : Pencil
104 : Pen
103 : Pen
b) 105 : sharpener
9
106 : scale
102 : Pencil
103 : Pen
104 : Pen
c) 103 : Pen
104 : Pen
102 : Pencil
106 : scale
105 : sharpener
d) 104 : Pen
103 : Pen
102 : Pencil
106 : scale
105 : sharpener
Answer: a)
Explanation: The implementation of functor compare sorts the product objects in descend-
ing order by the name (prod nam ) of the products. If any two product objects have same
name, then it will be sorted in descending order by the product number (prod num ) of the
students. Thus, a) is the correct option.
10
Programming Questions
Question 1
Consider the following program that finds the minimum element in an array. Fill in the blanks
as per the instructions given below:
• Fill in the blanks at LINE-2 and LINE-3 with appropriate conditional statement.
#include<iostream>
______________________________________ //LINE-1
void min(Itr first, Itr last, T& mv) {
mv = *first++;
while (__________________) { //LINE-2
if(__________________) //LINE-3
mv = *first;
++first;
}
}
int main(){
int iArr[10];
int n;
std::cin >> n;
for(int i = 0; i < n; i++)
std::cin >> iArr[i];
Public 1
Input:
5
50 27 10 70 23
Output: 10
Public 2
Input:
6
94 5 22 45 32 1
Output: 1
11
Private
Input:
4
10 20 40 30
Output: 10
Answer:
LINE-1: template<typename Itr, typename T>
or
LINE-1: template<class Itr, class T>
LINE-2: first != last
LINE-3: *first < mv
Explanation:
At LINE-1 we can declare the template as:
template<typename Itr, typename T>
or template<class Itr, class T>
At LINE-2 we have to provide a condition to check the end of the array, which can be written
as:
first != last
At LINE-3 we have to check whether mv is still the minimum value or not, which can be written
as: *first < mv
12
Question 2
Consider the following program that takes inputs a lower limit (l) and an upper limit (u) of
a vector. If all the elements of the input vector are within the given lower and upper limits,
the program prints ”all in [l, u]”. Otherwise, the program prints the first element of the vector
which is not within the given limits. Fill in the blanks as per the instructions given below:
• at LINE-1 with appropriate header to overload function operator,
• at LINE-2 with appropriate template definition,
• at LINE-3 with appropriate condition,
such that the program will satisfy the given test cases. Marks: 3
#include<iostream>
#include<vector>
struct Bound{
Bound(int l, int u) : l_(l), u_(u){}
___________________________{ //LINE-1
return (n >= l_ && n <= u_);
}
int l_, u_;
};
_______________________________ //LINE-2
Itr search(Itr first, Itr last, Pred bd) {
while (first != last){
if(___________________) //LINE-3
return first;
++first;
}
return first;
}
int main(){
int iArr[] = { 70, 20, 50, 40, 90, 10, 80 };
std::vector<int> iVec(iArr, iArr + sizeof(iArr) / sizeof(*iArr));
int l, u;
std::cin >> l >> u;
Bound bd(l, u);
if(it == iVec.end())
std::cout << "all in [" << l << ", " << u << "]";
else
std::cout << *it << " is the first element not in [" << l << ", " << u << "]";
return 0;
}
Public 1
Input: 10 100
13
Output: all in [10, 100]
Public 2
Input: 10 70
Output: 90 is the first element not in [10, 70]
Private
Input: 40 90
Output: 20 is the first element not in [40, 90]
Answer:
LINE-1: bool operator()(int n)
LINE-2: template<class Itr, class Pred>
or
LINE-2: template<typename Itr, typename Pred>
LINE-3: !bd(*first)
Explanation:
At LINE-1, the header to overload function operator is bool operator()(int n).
At LINE-2, the template for the search() function can be written as:
template<class Itr, class Pred>
or
template<typename Itr, typename Pred>
At LINE-3, the if condition can be written as:
if(!bd(*first))
14
Question 3
Consider the following program, which computes the frequency of occurrence (histogram) of
each integer in a given vector. Fill in the blanks as per the instructions given below:
• at LINE-2 with appropriate statement to iterate over the given map hi,
#include <iostream>
#include <map>
#include <vector>
int main() {
std::vector<int> vec;
for(int i = 0; i < 10; i++){
int a;
std::cin >> a;
vec.push_back(a);
}
std::map<int, int> hi = histo(vec);
print(hi);
return 0;
}
Public 1
Input: 9 4 5 3 4 6 7 4 3 5
Output: 3: 2, 4: 3, 5: 2, 6: 1, 7: 1, 9: 1,
Public 2
Input: 6 6 7 3 4 5 6 5 4 7
Output: 3: 1, 4: 2, 5: 2, 6: 3, 7: 2,
Private
Input: 1 3 4 5 3 3 2 1 4 3
Output: 1: 2, 2: 1, 3: 4, 4: 2, 5: 1,
15
Answer:
LINE-1: std::vector<int>::iterator it = v.begin(); it != v.end(); ++it
LINE-2: std::map<int,int>::iterator it = hi.begin(); it != hi.end(); ++it
Explanation:
The std::vector<int>::iterator type can be used to iterate through the given vector v, so
the statement at LINE-1 must be
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it
Similarly, the std::map<char,int>::iterator type can be used to iterate through the given
map hi, so the statement at LINE-2 must be
for (std::map<int,int>::iterator it = hi.begin(); it != hi.end(); ++it)
16
Programming in Modern C++: Assignment Week 10
Total Marks : 20
Question 1
Consider the code segment (in C++11) given below. [MSQ, Marks 2]
#include <iostream>
#include <list>
int main( ){
std::list<int> li { 10, 20, 30, 40, 50 };
int i = 0;
for(__________________________________________) // LINE-1
it *= 2;
1
Question 2
Consider the program (in C++11) given below. [MSQ, Marks 2]
#include <iostream>
int main( ){
int n = 10;
int& i1 = n;
const int& i2 = 10;
auto x1 = i1;
auto x2 = i2;
decltype(i1) x3 = i1;
decltype(i2) x4 = i1;
++x1; //LINE-1
++x2; //LINE-2
++x3; //LINE-3
++x4; //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: d)
Explanation:
Since auto never deduces adornments like cv-qualifer or reference (however, no error or excep-
tion is generated), the inferred type of x1 and x2 is int. For x3, the inferred type is int&,
whereas for x4, the inferred type is const int&. Therefore, d) is the correct option.
Intentionally kept as MSQ
2
Question 3
Consider the code segment (in C++14) given below. [MSQ, Marks 2]
#include<iostream>
int x = 10;
struct operation1 {
operation1(int val) : val_(val){}
int& operator()() { std::cout << val_ << " "; return x; }
int val_;
};
struct operation2 {
operation2(int val) : val_(val){}
int operator()() { std::cout << val_ << " "; return x; }
int val_;
};
int main(){
operation1 o1{1};
operation2 o2{2};
wrapper(o1) = 10;
int i = wrapper(o2);
return 0;
}
Identify the appropriate option/s to fill in the blank at LINE-1 such that output becomes 1 2.
Answer: a), d)
Explanation:
The call wrapper(o1) = 10; evaluates to lvalue of type int&.
The call wrapper(o2); evaluates to prvalue of type int.
Since plain auto never deduces to a reference, option b) fails for prvalue.
Since plain auto& always deduces to a reference, option b) fails for prvalue.
Option a) and d) works for lvalue as well as prvalue. Thus these two are correct options.
3
Question 4
Consider the code segment (C++11) given below. [MSQ, Marks 2]
#include<iostream>
int main(){
f1(10);
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: c), d)
Expanation:
constexpr needs compile-time constant.
At LINE-1, c1 = n + 30; where n is a constexpr and 30 is a literal. Therefore, c1 is a
constexpr.
At LINE-2, c2 = n + c1 where n and c1 both are constexpr. Therefore, c2 is a constexpr.
At LINE-3, c3 = n + i; where n is a constexpr; however i is not a compile-time constant.
Therefore, c2 cannot be constexpr.
At LINE-4, c4 = n + f2(i); where n is a constexpr; however the call f2(i) fails since i is not
a compile-time constant.
4
Question 5
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include <iostream>
#include <vector>
#include <initializer_list>
template<typename T>
class Numbers{
public:
Numbers() { std::cout << "cont-1" << " "; }
Numbers(int n) { std::cout << "cont-2" << " "; }
Numbers(std::initializer_list<int> elems) { std::cout << "cont-3" << " "; }
Numbers(int n, std::initializer_list<int> elms) { std::cout << "cont-4" << " ";
}
};
int main(){
Numbers<int> n1(10);
Numbers<int> n2({10, 20, 30});
Numbers<int> n3{10, 20, 30};
Numbers<int> n4 = {10, 20, 30};
Numbers<int> n5(10, {10, 20, 30});
return 0;
}
Answer: a)
Explanation:
Numbers<int> n1(10); invokes parameterized constructor Numbers(int n) { ... }.
Numbers<int> n2({10, 20, 30});, Numbers<int> n3{10, 20, 30}; and Numbers<int> n4
= {10, 20, 30}; invoke the initializer list constructor Numbers(initializer list<int> elms){
... }.
Numbers<int> n5(10, {10, 20, 30}); invokes the mixed constructor
Numbers(int n, initializer list<int> elms){ ... }.
5
Question 6
Consider the C++11 code segment below. [MSQ, Marks 2]
#include<iostream>
#include<iomanip>
int main() {
long len = _______________________________; //LINE-1
std::cout << len << "IN";
return 0;
}
Choose the appropriate option to fill in the blank at LINE-1, such that the output becomes
80IN.
a) 6.0FT + 8.0IN
b) 6.0_FT + 8.0_IN
c) (FT)6.0 + (IN)8.0
d) 6_FT + 8_IN
Answer: b)
Explanation: For user-defined numeric literal operators, the correct way to invoke them is
to write them as 6.0 FT + 8.0 IN.
All other options are compilation error. Even option d) is wrong as numeric literal operators
require exact type matching
Intentionally kept as MSQ
6
Question 7
Consider the program (in C++11) given below. [MCQ, Marks 2]
#include <iostream>
_______________________________ { // LINE-1
double divide(double n){
return n / 10;
}
}
_______________________________ { // LINE-2
template<typename T>
T divide(T n){
return n / 100;
}
}
int main(){
std::cout << ver1_0::divide(100.0) << " ";
std::cout << ver1_1::divide(100) << " ";
std::cout << divide(100.0);
return 0;
}
Choose the appropriate option to fill in the blanks at LINE-1 and LINE-2 so that the output
becomes
10 1 1
Answer: b)
Explanation:
As per the output of ver1 0::divide(10, 4) and ver1 1::divide(10, 4), the ver1 0 and
ver1 0 must have basic namespace definition. However, since divide(10, 4) invoke the func-
tion divide from ver1 1, ver1 1 must be the default namespace. Thus, at LINE-1 and LINE-2,
we must have:
namespace ver1 0
inline namespace ver1 1
7
Question 8
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
int main(){
int i = 10;
call(show, &i); //LINE-1
call(show, i); //LINE-2
call(show, NULL); //LINE-3
call(show, nullptr); //LINE-4
return 0;
}
Choose the call/s to call function that will result in compiler error/s.
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b), c)
Explanation:
For the call in LINE-1, the template type parameter Param is deduced to int*. Thus, it does
not generate any compiler error.
For the call in LINE-2, the template type parameter Param is deduced to int. Thus, it generates
a compiler error.
For the call in LINE-3, the template type parameter Param is deduced to long int (which is
the datatype of NULL). Thus, it generates a compiler error.
For the call in LINE-4, the template type parameter Param is deduced to std::nullptr t and
the call show(std::nullptr t) is syntactically correct.
8
Question 9
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include<iostream>
#include<utility>
class number{
public:
number(const int& i = 0) : i_(i) { }
number(const number& ob) {
std::cout << "number-cp-ctor" << " ";
}
number(number&& ob) noexcept {
std::cout << "number-mv-ctor" << " ";
}
private:
int i_;
};
int main(){
sp_number obj1(100);
sp_number obj2(obj1);
sp_number obj3(std::move(obj1));
return 0;
}
Answer: d)
Explanation:
Since the constructors are invoked in a top-down order in C++ class hierarchy, the construc-
tion for the given program takes place as follows:
The statement sp number obj2(obj1); calls the copy constructor of sp number, which for-
ward the call to the copy constructor of number. Thus, it prints
number-cp-ctor spnumber-cp-ctor
9
The statement sp number obj3(std::move(obj1)); calls the move constructor of sp number,
which forward the call to the copy constructor of number. Thus, it prints
number-cp-ctor spnumber-mv-ctor
10
Programming Questions
Question 1
Consider the following program in C++11/14 to convert between feet and inch. Fill in the
blanks as per the instructions given below:
• at LINE-1 with appropriate header to function convert,
class feet;
class inch{
public:
inch(double i) : i_(i){}
feet getValue();
void show(){ std::cout << i_ << " "; }
private:
double i_;
};
class feet{
public:
feet(double f) : f_(f){}
inch getValue();
void show(){ std::cout << f_ << " "; }
private:
double f_;
};
feet inch::getValue(){
feet t(i_ / 12.0);
return t;
}
inch feet::getValue(){
inch t(f_ * 12.0);
return t;
}
int main(){
double a, b;
std::cin >> a >> b;
feet f(a);
11
inch i(b);
inch i1 = convert(f);
feet f1 = convert(i);
i1.show();
f1.show();
return 0;
}
Public 1
Input: 12 12
Output: 144 1
Public 2
Input: 90 90
Output: 1080 7.5
Private
Input: 12 120
Output: 144 10
Answer:
LINE-1: auto convert(T n) -> decltype(n.getValue()) //in C++11
LINE-1: decltype(auto) convert(T n) //in C++14
LINE-2: return n.getValue()
Explanation:
The function convert must have a trailing return type. Thus, the header of convert function
should be:
auto convert(T n) -> decltype(getValue(n)) //in C++11
decltype(auto) convert(T n) //in C++14
The body of the function should be:
return getValue(n);
Note that return type of convert() is different from its parameter type T and depends on the
return type of getValue(). So it is difficult to write this template in C++03
12
Question 2
Consider the following program in C++11/14. Fill in the blanks as per the instructions given
below:
• at LINE-1 with appropriate header and initialization list for the copy constructor,
• at LINE-3 with appropriate header and initialization list for the move constructor,
#include <iostream>
#include <vector>
class number {
public:
number(){}
number(int i) : ip_(new int(i)) { }
______________________________ { } // LINE-1: copy constructor
______________________________ { // LINE-2: copy assignment
if (this != &n) {
delete ip_;
ip_ = new int(*(n.ip_) * 10);
}
return *this;
}
~number() { delete ip_; }
____________________________ { n.ip_ = nullptr; } // LINE-3: move constructor
_______________________________ { // LINE-4: move assignment
if (this != &d) {
ip_ = d.ip_;
d.ip_ = nullptr;
}
return *this;
}
void show(){
if(ip_ == nullptr)
std::cout << "moved : ";
else
std::cout << *ip_ << " : ";
}
private:
int* ip_ {nullptr};
};
int main(){
int a;
std::cin >> a;
number n1(a);
number n2 = n1;
13
number n3;
n3 = n1;
n1.show();
n2.show();
n3.show();
number n4 = std::move(n1);
number n5;
n5 = std::move(n1);
n1.show();
n4.show();
n5.show();
return 0;
}
Public 1
Input: 5
Output: 5 : 50 : 50 : moved : 5 : moved :
Public 2
Input: -10
Output: -10 : -100 : -100 : moved : -10 : moved :
Private
Input: 1
Output: 1 : 10 : 10 : moved : 1 : moved :
Answer:
LINE-1: number(const number& n) : ip (new int(*(n.ip ) * 10))
LINE-2: number& operator=(const number& n)
LINE-3: number(number&& n) : ip (n.ip )
LINE-4: number& operator=(number&& d)
Explanation:
As per the output specified, the header and initialization list for copy constructor at LINE-1
is:
number(const number& n) : ip (new int(*(n.ip ) * 10)),
the header for copy assignment operator for copy assignment is:
number& operator=(const number& n),
the header and initialization list for move constructor at LINE-3 is:
number(number&& n) : ip (n.ip ),
the header for move assignment at LINE-4 is:
number& operator=(number&& d).
14
Programming in Modern C++: Assignment Week 11
Total Marks : 20
Question 1
Consider the code segment (in C++11) given below. [MSQ, Marks 2]
template<typename T1>
class RefType{
public:
void f1(T1&& n){} //LINE-1
template<typename T2>
void f2(T2&& n){} //LINE-2
template<typename T3>
void f3(std::list<T3>&& n); //LINE-3
private:
auto&& n; //LINE-4
};
Identify the line/s where && indicates a universal reference.
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b), d)
Explanation:
Note that && usually indicates rvalue reference. && indicates a universal reference only where
type deduction takes place.
At LINE-1, no type deduction takes place during function call (the type deduction takes place
during class instantiation), therefore && at LINE-1 is just a rvalue reference, not a universal
reference.
At LINE-2, the template type parameter T2 requires type deduction. Thus, && at LINE-2
indicates a universal reference.
At LINE-3, the template type parameter T3 requires type deduction. However, since the form
of function parameter is not T&& (it in form std::list<T>&&), it indicates only rvalue refer-
ence. At LINE-4, like template auto also requires type deduction. Therefore && at LINE-2
indicates a universal reference.
1
Question 2
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
template<typename T>
class Data{
public:
Data() {};
Data(T i) : i_(i){ }
Data(const Data& ) = delete;
Data& operator=(const Data& ) = default;
Data(Data&& ) = default;
private:
T i_;
};
int main(){
Data<int> d1;
Data<int> d2(30); //LINE-1
Data<int> d3 = d2; //LINE-2
Data<int> d4 = std::move(d2); //LINE-3
d1 = std::move(d2); //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b)
Explanation:
Since the copy constructor of class Data are explicitly deleted, LINE-2 generates compiler error.
Please note that though the move assignment operator is not defined, the statement at LINE-4
will not generate error because if move assignment operator is not present it calls copy assign-
ment operator by default.
2
Question 3
Consider the following code segment (in C++11). [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main() {
std::vector<std::string> v {"orange", "banana", "apple", "kiwi"};
process(v);
for(auto it : v)
std::cout << it << " ";
return 0;
}
Answer: c)
Explanation:
C++11 allows local declaration of functor within function scope, so it is not a compiler error.
Furthermore, since the vector is passed as pass-by-reference, the effect of the sort would be
reflected on the vector in main function. As per the logic implemented in functor cmp, sort
would sort the vector in descending order of the length of the strings.
3
Question 4
Consider the code segment (C++11) given below. [MSQ, Marks 2]
#include <iostream>
class data {
public:
data(){}
explicit data(int i) : i_(i) { }
protected:
int i_ { 0 };
};
int main(){
data_pair d1(10);
data_pair d2(10.5);
d1.show();
d2.show();
return 0;
}
Choose the appropriate option/options to fill in the blank at LINE-1 such that output becomes
(10, 0) (0, 10.5) .
b) using data::data;
Answer: b), c)
Explanation:
The statement data pair d1(10); requires to initialize i which means it needs to call the
constructor of data within data pair. Therefore, at LINE-1 we fetch the base class data
constructor as using data::data;.
Alternatively, we can have another constructor in data pair which forward the call to the base
class.
4
Question 5
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
#include <vector>
int main(){
double sum = 0.0, avg = 0.0;
______________________________________ { //LINE-1
for(auto it : v)
sum += it;
return sum / v.size();
};
std::vector<double>vd {10.6, 20.4, 30.4, 40.2};
avg = stat(vd);
std::cout << "avg = " << avg << ", sum = " << sum;
return 0;
}
Identify the appropriate option(s) to fill in the blanks at LINE-1 such that the output becomes
avg = 25.4, sum = 101.6.
Answer: a), d)
Explanation:
Since the variable sum is modified within the lambda function it needs to be captured by
reference. However, variable avg is not required to be captured as it is returned as result of
the function.
5
Question 6
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include <iostream>
class employee{
public:
explicit employee() : employee(0) {} //LINE-1
explicit employee(const int emp_id) :
employee(emp_id, defaultSalary) {} //LINE-2
explicit employee(const double salary) : employee(0, salary) {} //LINE-3
explicit employee(int emp_id, double salary) : emp_id_{emp_id},
salary_{salary} {} //LINE-4
friend std::ostream& operator<<(std::ostream&, const employee&);
private:
int emp_id_ {-1};
double salary_ {0.0};
static constexpr double defaultSalary {20000.00};
};
int main(){
employee e1;
employee e2(10); //LINE-5
employee e3(60000.0); //LINE-6
employee e4(20, 75000.5);
std::cout << e1 << e2 << e3 << e4;
return 0;
}
Answer: b)
Expanation:
The statement at LINE-5 call the default constructor at LINE-1, which delegates the call to
the parameterized constructor at LINE-2, which further delegates the call to the parameterized
constructor at LINE-4.
6
Question 7
Consider the code segment (C++14) given below. [MCQ, Marks 2]
#include <iostream>
a) 6, 6.28571, 6.28571, 6
Answer: c)
Explanation:
In the expression: [](auto(deg)) return pi<decltype(deg)> * deg / 180; (360) , the
inferred type of deg is int. So, the result is 200.
In the expression: [](auto(deg)) return pi<double> * deg / 180; (360) , the pi<double>
is 3.1415926535897932385L. So, the result is 6.28571.
In the expression: [](auto(deg)) return pi<decltype(deg)> * deg / 180; (360.0) ,
the inferred type of deg is double. So, the result is 6.28571.
In the expression: [](auto(deg)) return pi<int> * deg / 180; (360.0) , the pi<int>
is 100. So, the result is 200.
7
Question 8
Consider the lambda function (in C++11) below. [MCQ, Marks 2]
Identify the correct option that define the equivalent Closure object for the above lambda
function.
a) struct process_s {
std::vector<double> hv;
double& fact;
std::vector<int> v;
process_s(std::vector<int> _v) : v(_v) { }
void operator()(std::vector<double> _hv, double& _fact) const {
for(auto it : v)
hv.push_back(it * fact);
}
};
std::vector<int> vc{10, 20, 30};
auto process = process_s(vc);
b) struct process_s {
std::vector<double> hv;
double& fact;
process_s(std::vector<double> _hv, double& _fact) : hv(_hv), fact(_fact) { }
void operator()(std::vector<int> v) const {
for(auto it : v)
hv.push_back(it * fact);
}
};
auto process = process_s(hv, fact);
c) struct process_s {
std::vector<double>& hv;
double fact;
process_s(std::vector<double>& _hv, double _fact) : hv(_hv), fact(_fact) { }
void operator()(std::vector<int> v) const {
for(auto it : v)
hv.push_back(it * fact);
}
};
auto process = process_s(hv, fact);
d) struct process_s {
std::vector<double> hv;
double fact;
process_s(std::vector<double> _hv, double _fact) : hv(_hv), fact(_fact) { }
void operator()(std::vector<int> v) const {
8
for(auto it : v)
hv.push_back(it * fact);
}
};
auto process = process_s(hv, fact);
Answer: c)
Explanation:
For a λ-expression, the compiler creates a functor class with:
• data members:
• a public inline const function call operator() with the parameters of the lambda as
parameters, generated from the body of the lambda
9
Question 9
Consider the following code segment (in C++11). [MSQ, Marks 2]
Identify the statement/s which are true for the above code segment.
Answer: b), c)
Explanation:
The statement if(type == SIGNAL::RED) compares between two SIGNAL type elements, which
compiles successfully.
The statement if(col == COLOR::GREEN) compares between SIGNAL type with COLOR type,
which are not type castable. Thus it generates error.
The statement if(col == YELLOW) compares between SIGNAL type with int, which are not
type castable. Thus it generates error.
10
Programming Questions
Question 1
Consider the following program (in C++11).
• Fill in the blanks at LINE-1 and LINE-3 with appropriate template definitions.
• Fill in the blanks at LINE-2 and LINE-4 to complete the return statements for product
functions.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
_____________________________ //LINE-1
double product(T num){ ___________________ } //LINE-2
_____________________________ //LINE-3
double product(T num, Tail... nums){
return num * _____________________; //LINE-4
}
int main(){
int a, b, c;
double d, e, f;
std::cin >> a >> b >> c;
std::cin >> d >> e >> f;
std::cout << product(a, b, c) << " ";
std::cout << product(d, e, f) << " ";
std::cout << product(a, b, c, d, e, f);
return 0;
}
Public 1
Input:
2 3 4
2.3 3.4 4.6
Output:
24 35.972 863.328
Public 2
Input:
10 20 30
1.5 2.3 -4.5
Output:
6000 -15.525 -93150
Private
Input:
10 -11 12
2.3 2.5 2.7
11
Output:
-1320 15.525 -20493
Answer:
LINE-1: template <typename T>
or
LINE-1: template <class T>
LINE-2: return num;
LINE-3: template <typename T, typename... Tail>
or
LINE-3: template <class T, class... Tail>
LINE-4: product(nums...)
Explanation:
At LINE-1, the definition of the simple template is:
template <typename T>
or
template <class T>
, and at LINE-3 the return statement the function product is:
return num;
At LINE-3, the definition of the veriadic template is:
template <typename T, typename... Tail>
or
template <class T, class... Tail>
, and at LINE-4 the complete the return statment of function product as:
return num * product(nums...);
12
Question 2
Consider the program below (in C++11).
• Fill in the blanks at LINE-2 with an appropriate universal reference type parameter for
constructor of class derived and an the appropriate call forwarding to the base class
constructor.
#include <iostream>
class base {
public:
base(const int& n) : n_(n * 10){ std::cout << "lvalue : " << n << ", "; }
base(int&& n) : n_(n * 20) { std::cout << "rvalue : " << n << ", "; }
protected:
int n_;
};
Public 1
Input: 10
Output: lvalue : 10, rvalue : 10, 100 200
Public 2
Input: 50
Output: lvalue : 50, rvalue : 50, 500 1000
Private
Input: 5
Output: lvalue : 5, rvalue : 5, 50 100
Answer:
LINE-1: template<typename T>
13
or
LINE-1: template<class T>
LINE-2: derived(T&& n) : base(std::forward<T>(n))
Explanation:
At LINE-1 the template must be declared as:
template<typename T>
or
template<class T>
At LINE-2, universal reference type parameter for constructor of class derived and the call
forwarding to base class can be done as:
derived(T&& n) : base(std::forward<T>(n))
14
Question 3
Consider the following program that implements a recursive lambda function to find the sum
of the digits of an input integer.
• Fill the blank at LINE-2 to complete the definition of lambda function revPrint.
The program must satisfy the sample input and output. Marks: 3
#include<iostream>
#include<functional>
int main() {
_____________________________________; //LINE-1
int a;
std::cin >> a;
std::cout << revPrint(a);
}
Public 1
Input: 12345
Output: 15
Public 2
Input: 4343
Output: 14
Private
Input: 1045
Output: 10
Answer:
LINE-1: std::function<int(int)> revPrint
LINE-2: [&revPrint](int n) -> int
Explanation:
At LINE-1, we can use std::function to declare the signature of revPrint as:
std::function<int(int)> revPrint
At LINE-2 to complete the definition of lambda function revPrint is as follows:
15
return n % 10 + revPrint(n /= 10);
};
16
Programming in Modern C++: Assignment Week 12
Total Marks : 20
October 6, 2023
Question 1
Which of the following types of smart pointers follow/s exclusive ownership policy? [MSQ,
Marks 2]
a) std::auto ptr
b) std::unique ptr
c) std::std::shared ptr
d) std::weak ptr
Answer: a), b)
Explanation:
std::auto ptr (C++03) and std::unique ptr (C++11) are the two smart pointer types
that support exclusive ownership policy.
std::std::shared ptr (C++11) and std::weak ptr (C++11) are the two smart pointer
types that support shared ownership policy.
1
Question 2
Consider the program (in C++11) given below. [MSQ, Marks 2]
#include <iostream>
#include <thread>
#include <list>
#include <functional>
struct Stat {
std::list<int>& iLst;
int* sum;
int* avg;
Stat(std::list<int>& il, int* s, int* a) : iLst{il}, sum(s), avg(a) { }
void operator()() {
int j = 0;
for(auto& i : iLst) {
*sum += i;
i = ++j;
}
*avg = *sum / j;
}
};
int main() {
std::list<int> il { 10, 20, 30 };
int s = 0, a = 0;
std::thread t { ____________________ }; //LINE-1
t.join();
show(il);
std::cout << s << " " << a;
return 0;
}
Fill in the blank at LINE-1 with appropriate option(s) such that the output becomes 1 2 3
60 20.
d) std::bind(Stat, std::ref(il), s, a)
Answer: b), c)
Explanation:
The constructor of Stat receives li as pass-by-reference, and s and a as pass-by-address.
Therefore, the options b) and c) are correct. Note that std::ref function also enables pass-
by-reference.
2
Question 3
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include<iostream>
template<typename T>
class SmartPtr {
public:
explicit SmartPtr(T* pointee): pointee_(pointee) { }
~SmartPtr() { delete pointee_; }
_____________________ { return pointee_; } //LINE-1
private:
T* pointee_;
};
int main(){
SmartPtr<char> p(new char(’A’));
std::cout << *p << " "; //LINE-1
incr(p);
std::cout << *p; //LINE-2
return 0;
}
Fill in the blank at LINE-1 with appropriate option(s) such that the output becomes A B.
b) operator T*()
c) T* operator->() const
d) operator void*()
Answer: b)
Explanation:
Since LINE-1 and LINE-2 need to print SmartPtr as char, we have to implement the corre-
sponding typecasting operator. Therefore, option b) is the correct option.
3
Question 4
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include<iostream>
template<typename T>
class SmartPtr {
public:
explicit SmartPtr(T* pointee): pointee_(pointee) { }
~SmartPtr() { delete pointee_; }
T& operator*() const { return *pointee_; }
T* operator->() const { return pointee_; }
operator T*() { return pointee_; }
operator void*() { return pointee_; }
private:
T* pointee_;
};
int main(){
SmartPtr<char> p(new char(’A’));
std::cout << *p << " "; //LINE-1
incr(p);
std::cout << *p; //LINE-2
delete p; //LINE-3
return 0;
}
a) A B
b) A A
Answer: d)
Explanation:
The statement delete p; generates a compiler error since the compiler cannot decide which
conversion (either to char* or to void*) to apply. Thus, it results in ambiguous default
type conversion from ‘SmartPtr’.
4
Question 5
Consider the following code segment (int C++11). [MCQ, Marks 2]
#include <iostream>
#include <functional>
a) -8 -8
b) -11 19
c) -12 18
d) -8 22
Answer: d)
Explanation:
The call wf(5, 6, 7) results in binding 5 to 1, 6 to 2 (which is not used), and 3 to 3. The
formal arguments for the first call to compute are as fun(7, 10, 5, 20), which is evaluated
as -8. The formal arguments for the second call to compute are as print(7, 10, 5, -10)
(since b is considered as reference type in bind function), which is evaluated as 22.
5
Question 6
Consider the code segment (C++11) given below. [MCQ, Marks 2]
#include<iostream>
#include <memory>
a) rc = 2 rc = 3 rc = 3 rc = 1
b) rc = 2 rc = 3 rc = 3 rc = 2
c) rc = 2 rc = 4 rc = 2 rc = 1
d) rc = 2 rc = 4 rc = 2 rc = 2
Answer: c)
Explanation:
The code is explained in the comment:
#include<iostream>
#include <memory>
6
std::cout << "rc = " << cp1.use_count() << " "; //rc = 3
cp3.reset(new char(’B’)); //rc = 1
std::cout << "rc = " << cp1.use_count();
return 0;
}
7
Question 7
Consider the code segment (C++11) given below. [MSQ, Marks 2]
#include <iostream>
#include <list>
#include <thread>
int main(){
std::list<char> lc;
for(int i = 0; i < 2; i++)
lc.push_back(’A’ + i);
std::thread t1 {std::ref(addToList), std::ref(lc)};
t1.join();
for(char c : lc)
std::cout << c << " ";
return 0;
}
a) A C B
b) A B C
c) C A B
d) It prints nothing
Answer: b)
Explanation:
The main adds ’A’ and ’B’ to the std::list<char> lc, and then create the thread. The
execution of the thread t1 must be completed before (due to join call) printing the list in
main. Thus, it always prints A B C.
Intentionally kept as MSQ.
8
Question 8
Consider the following program (in C++11). [MSQ, Marks 2]
#include <iostream>
#include <functional>
#include <thread>
#include <mutex>
struct ResourceA{
int RAC;
};
struct ResourceB{
int RBC;
};
std::mutex RA_mtx;
std::mutex RB_mtx;
int main(){
ResourceA rA{0};
ResourceB rB{0};
std::thread t1{ std::bind(req1, std::ref(rA), std::ref(rB), 5, 5) };
std::thread t2{ std::bind(req2, std::ref(rA), std::ref(rB), 4, 4) };
t1.join();
t2.join();
return 0;
}
Identify the statement/s that is/are not true about the program.
a) It generates output as:
REQ2: 4 4
REQ1: 9 9
b) It generates output as:
REQ1: 5 5
REQ2: 4 4
9
c) It generates output as:
REQ1: 5 5
REQ2: 9 9
d) It results in deadlock
Answer: b)
Explanation:
Since the code in req1 and req2 execute in a mutual exclusive manner, the output can be:
REQ1: 5 5
REQ2: 9 9
or
REQ2: 4 4
REQ1: 9 9
However, it cannot be
REQ1: 5 5
REQ2: 4 4
It may also happen that t1 holds lock on RA mtx, and t2 holds lock on RB mtx. Then, t1
request to lock on RB mtx, and t2 requests lock on RA mtx. It results in a deadlock. Therefore,
b) is the correct option.
Intentionally kept as MSQ
10
Question 9
Consider the following code segment (in C++11). [MCQ, Marks 2]
#include <iostream>
#include <future>
#include <list>
struct Prod{
Prod(const std::list<int>& dl) : dl_(dl) { }
double operator()() {
int p = 1;
for(int it : dl_)
p *= it;
return p;
}
std::list<int> dl_;
};
int main() {
std::list<int> dLi {2, 4, 6, 2, 5};
std::cout << callProd(dLi);
return 0;
}
Choose the appropriate option to fill in the blank at LINE-1 such that output becomes 480.
a) std::thread(Prod(dl))
b) std::thread{std::bind(Prod(dl))}
c) std::async(Prod(dl))
d) std::atomic(std::ref(Prod(dl)))
Answer: c)
Explanation:
Since as.get() must be waiting for fullfillment of the promise, which the return value of Prod,
the call at LINE-1 must be std::async(Prod(dl)).
11
Programming Questions
Question 1
Consider the following program (in C++11).
• Fill in the blank at LINE-1 with appropriate header to overload function operator.
• Fill the blank at LINE-3 to receive the output from functor Factorial().
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
#include <future>
struct Factorial{
Factorial(const long long& n) : n_( n) { }
______________________________________ { //LINE-1
long long f = 1;
if(n_ == 0 || n_ == 1)
return 1;
for(int i = 1; i <= n_; i++)
f *= i;
return f;
}
const long long n_;
};
int main() {
int n;
std::cin >> n;
std::cout << callFacto(n);
return 0;
}
Public 1
Input: 10
Output: 3628800
Public 2
Input: 3
Output: 6
12
Private
Input: 11
Output: 39916800
Answer:
LINE-1: long long operator()()
LINE-2: std::async(Factorial(n))
LINE-3: a.get()
Explanation:
The function header at LINE-1 to overload the function operator can be: long long operator()()
At LINE-2 the asynchronous call to the functor Factorial() can be made as:
auto a = std::async(Factorial(n))
At LINE-3 can use the statement a.get() to receive the result of functor Factorial().
13
Question 2
Consider the following program (in C++11).
• Fill the blanks at LINE-2 and LINE-4 by locking the mutex object.
• Fill the blanks at LINE-3 and LINE-5 by unlocking the mutex object.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
#include <thread>
#include <functional>
#include <chrono>
#include <mutex>
_________________________; //LINE-1
class muffin_store {
public:
muffin_store() : n_muffins(0) {};
void in_stock(int m){
________________________; //LINE-2
update_amount = m;
int delay = (int)((double)std::rand() / (double)(RAND_MAX)* 20);
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
n_muffins += update_amount;
________________________; //LINE-3
}
void out_stock(int m){
________________________; //LINE-4
update_amount = m;
int delay = (int)((double)std::rand() / (double)(RAND_MAX)* 40);
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
n_muffins -= update_amount;
________________________; //LINE-5
}
void show_stock() { std::cout << n_muffins; }
private:
int n_muffins;
int update_amount;
};
14
for(int i = n; i >= 1; i--){
int delay = (int)((double)std::rand() / (double)(RAND_MAX)* 30);
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
ms.out_stock(i * 10);
}
}
int main(){
int n, m;
std::cin >> n >> m;
muffin_store ms;
std::thread t1{ std::bind(incoming_muffin, std::ref(ms), n) };
std::thread t2{ std::bind(outgoing_muffin, std::ref(ms), m) };
t1.join();
t2.join();
ms.show_stock();
return 0;
}
Public 1
Input: 10 10
Output: 0
Public 2
Input: 20 10
Output: 1550
Private
Input: 10 20
Output: -1550
Answer:
LINE-1: std::mutex mf mtx;
LINE-2: mf mtx.lock()
LINE-3: mf mtx.unlock()
LINE-4: mf mtx.lock()
LINE-5: mf mtx.unlock()
Explanation:
At LINE-1, the mutex object can be created as:
std::mutex ac mtx;
At LINE-2 and LINE-4, locking of the mutex object can be written as:
ac mtx.lock()
At LINE-3 and LINE-5, unlocking of the mutex object can be written as:
ac mtx.unlock()
15
Question 3
Consider the following program in C++14 to represent a generic deque (double-ended-queue),
which allows adding items at the front of the queue and at the end of the queue. Complete
the program as per the instructions given below.
• Fill in the blank at LINE-1 with appropriate statements so that after execution of the
for loop, t refers to the last element of the deque.
• Fill in the blank at LINE-2 with appropriate statements to traverse the list in forward
direction.
• fill in the blank at LINE-3 with appropriate statements to traverse the list in backward
direction,
The program must satisfy the sample input and output. Marks: 3
#include<iostream>
#include<memory>
namespace DS{
template<typename T1>
class deque;
template<typename T2>
class node{
public:
node(T2 _info) : info(_info), next(nullptr) {}
friend deque<T2>;
private:
T2 info;
std::shared_ptr<node<T2>> next;
std::weak_ptr<node<T2>> prev;
};
template<typename T1>
class deque{
public:
deque() = default;
void addFront(const T1& item){
std::shared_ptr<node<T1>> n = std::make_shared<node<T1>>(item);
if(first == nullptr){
first = n;
last = first;
}
else{
n->next = first;
first->prev = n;
first = n;
}
}
void addEnd(const T1& item){
std::shared_ptr<node<T1>> n = std::make_shared<node<T1>>(item);
if(first == nullptr){
16
first = n;
last = first;
}
else{
std::shared_ptr<node<T1>> t = first;
for(___________________________________________); //LINE-1
t->next = n;
n->prev = t;
last = n;
}
}
void traverse(){
for(_______________________________________________) //LINE-1
std::cout << t->info << " ";
}
void rev_traverse(){
for(______________________________________________) //LINE-2
std::cout << p->info << " ";
}
private:
std::shared_ptr<node<T1>> first { nullptr };
std::shared_ptr<node<T1>> last { nullptr };
};
}
int main(){
DS::deque<int> il;
int n, a;
std::cin >> n;
for(int i = 0; i < n; i++){
std::cin >> a;
il.addFront(a);
}
for(int i = 0; i < n; i++){
std::cin >> a;
il.addEnd(a);
}
il.traverse();
std::cout << std::endl;
il.rev_traverse();
return 0;
}
Public 1
Input:
4
10 20 30 40
50 60 70 80
Output:
40 30 20 10 50 60 70 80
80 70 60 50 10 20 30 40
17
Public 2
Input:
3
10 20 30
40 50 60
Output:
30 20 10 40 50 60
60 50 40 10 20 30
Public 3
Input:
2
8 9
7 5
Output:
9 8 7 5
5 7 8 9
Private
Input:
5
1 2 3 4 5
6 7 8 9 10
Output:
5 4 3 2 1 6 7 8 9 10
10 9 8 7 6 1 2 3 4 5
Answer:
LINE-1: ; t->next != nullptr; t = t->next
LINE-2: std::shared ptr<node<T1>> t = first; t != nullptr; t = t->next
LINE-3: std::weak ptr<node<T1>> t = last; auto p = t.lock(); t = p->prev
Explanation:
To add a node at the end of the deque, we can find that t is already initialized to the first
element of the deque. Therefore, the for loop can be written as follows:
std::shared ptr<node<T1>> t = first;
for(; t->next != nullptr; t = t->next);
The ; at the end of for loop indicate an empty statement. Since in class node, next is a
shared ptr, the for loop for forward traversal must be:
std::shared ptr<node<T>> t = first; t != nullptr; t = t->next)
Since in class node, prev is a weak ptr, the for loop for reverse traversal must be:
std::weak ptr<node<T>> t = last; auto p = t.lock(); t = p->prev
Note that last is a shared ptr while prev is a weak ptr. So we need to devise a way to
navigate between the two. Recall that weak ptr cannot be used to access the the pointee. So
we first get weak ptr t from last. Now for access, we get a shared ptr p by locking the
weak ptr t. This will used in the loop body. Finally, to progress backward, we get p->prev
and keep in the weak ptr t. That completes the solution.
18