C++ 2024H1 Assignment-7
C++ 2024H1 Assignment-7
Total Marks : 25
Question 1
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class student {
int roll ;
int marks;
public:
student(int _r, int _m) : roll(_r), marks(_m) {}
void update(int m) const{
(____________________)->marks = m; //LINE-1
}
void showInfo() const {
cout << roll << " : " << marks;
}
};
int main(void) {
const student s(3000, 56);
s.update(50);
s.showInfo();
return 0;
}
Fill in the blank at LINE-1 such that the program will print 3000 : 50.
a) const cast <student*> (this)
d) (student*)(this)
Answer: a), d)
Explanation:
The statement const student s(3000, 56); defines s as a constant object. To modify its
data members, the constant-ness of the object needs to be removed. This can be done either
by const cast (in option a) or casting constant this pointer to student* type (in option d).
1
Question 2
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
int main() {
char c = ’C’;
int d = 10;
char *cp = &c;
int *pd;
c = static_cast<char>(d); // LINE-1
d = static_cast<int>(c); // LINE-2
pd = static_cast<int*>(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.
2
Question 3
Consider the following code segment. [MSQ, Marks 2]
class Test1 { };
class Test2 : public Test1 { };
int main(){
Test1* t1 = new Test1;
Test2* t2 = new Test2;
t2 = __________________(t1);
return 0;
}
Fill in the blank at LINE-1 such that the program will be compiled successfully.
a) static cast<Test2*>
b) dynamic cast<Test2*>
c) reinterpret cast<Test2*>
d) const cast<Test2*>
Answer: a), c)
Explanation:
On each option, there is an attempt to cast from Test1* to Test2*. As we know, 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. Moreover, static cast is used to convert a base class object to a derived
class object. Hence option a) and c) are correct.
3
Question 4
Consider the following code segment. [MCQ, Marks 2]
class Test1 { };
class Test2 { };
Test1* t1 = new Test1;
Test2* t2 = new Test2;
a) t2 = static cast<Test2*>(t1);
b) t2 = dynamic cast<Test2*>(t1);
c) t2 = reinterpret cast<Test2*>(t1);
d) t2 = const cast<Test2*>(t1);
Answer: c)
Explanation:
On each option, there is an attempt to cast from Test1* to Test2*, 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 c) is correct.
4
Question 5
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
#include <typeinfo>
using namespace std;
class B { public: ~B(){}};
class D: public B {};
int main() {
B b;
D d;
D *dp = &d;
B *bp = dp;
D *dpp = (D*)dp;
cout << (typeid(bp).name() == typeid(dpp).name());
cout << (typeid(*bp).name() == typeid(*dpp).name());
cout << (typeid(dp).name() == typeid(dpp).name());
cout << (typeid(*dp).name() == typeid(*dpp).name());
return 0;
}
a) 0101
b) 0111
c) 0110
d) 0011
Answer: d)
Explanation:
Type of bp is B* and type of dpp is D*. Thus, output is 0.
*bp and *dpp point to the same object d, and it is a static binding situation. Thus, both are
of type D and output is 0.
Type of dp and dpp is D*. Thus, output is 1.
*dp and *dpp point to the same object d, and it is a dynamic binding situation. Thus, both
are of type D and output is 1.
5
Question 6
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class A{ public: virtual ~A(){} };
class B : public A{};
class C : public A{};
int main(){
A objA;
B objB;
A* pA = dynamic_cast<A*>(&objB); //LINE-1
pA == NULL ? cout << "A" : cout << "B";
B* pB = dynamic_cast<B*>(pA); //LINE-2
pB == NULL ? cout << "A" : cout << "B";
C* pC = dynamic_cast<C*>(new A); //LINE-3
pC == NULL ? cout << "A" : cout << "B";
pC = dynamic_cast<C*>(&objB); //LINE-4
pC == NULL ? cout << "A" : cout << "B";
return 0;
}
a) ABAB
b) BABA
c) BBAA
d) BABB
Answer: c)
Explanation:
The type-casting at LINE-1 is valid as it is an upper-casting. Hence, prints B.
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 B). Hence, prints B.
At LINE-3, the down-casting is invalid as the pointer pC points to parent type of object (which
is of type A). Hence prints A.
At LINE-4, the casting is also invalid as the pointer pC points to an object (which is of type
B) that is neither of its base type or derived type and hence prints A.
6
Question 7
Consider the following code segment. [MSQ, Marks 2]
#include<iostream>
using namespace std;
class A{
public:
virtual void F() {}
void G() {}
};
class B : public A{
public:
virtual void G() {}
void H() {}
virtual void I();
};
class C : public B{
public:
void G() {}
virtual void H() {}
};
class D : public C{
public:
void H() {}
};
a) A::F(A* const)
C::G(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::G(B* const)
B::H(B* const)
C::I(C* const)
d) A::F(A* const)
B::G(C* const)
C::H(C* const)
C::I(C* const)
Answer: a)
Explanation:
7
All four functions are virtual in the class C. So, there will be four entries in virtual function
table.
Now function F() is not overridden in class B and C. So, the entry for function F() in the
virtual function table of class C will be A::F(A* const).
The function G() is virtual from class B and is overridden in class C. So, the entry for function
G() in VFT of class C will be C::G(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).
Also, I() will be in the VFT as B::I(B* const)
8
Question 8
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
int main() {
const int i = 100;
const int *pi = &i;
int *qi = __________________(pi); //LINE-1
*qi = 200;
cout << *qi;
return 0;
}
Fill in the blank at LINE-1 so that the program will print ”200”.
a) const cast<int*>
b) static cast<int*>
c) dynamic cast<int*>
d) (int*)
Answer: a), d)
Explanation:
At LINE-1, pi of type const int* needs to be casted to int*. It can be accomplished by
const cast<int*>(pi) or (int*).
9
Question 9
Consider the code segment given below. [MCQ, Marks 2]
class Person {
public:
virtual void sleep() = 0;
virtual void work() {};
};
class Man: public Person {
public:
void sleep() {};
virtual void work() {};
};
class Woman: public Person{
public:
void sleep() {}
void work(){}
};
class Child{
public:
void play() {};
void cry() {};
};
a) 1
b) 2
c) 3
d) 4
Answer: c)
Explanation:
All the classes Person, Man and Woman consist of some virtual functions. Thus, 3 virtual
function tables would be created.
The class Child does not have any virtual function. So no virtual function tables would be
created.
10
Programming Questions
Question 1
Complete the program with the following instructions.
• Fill in the blank at LINE-1 to complete operator overloading for assignment operator.
• Fill in the blanks at LINE-2 and LINE-3 to complete the type casting statements.
The program must satisfy the given test cases. Marks: 3
#include<iostream>
using namespace std;
class Test1{
int a = 10;
public:
void show(){
cout << a ;
}
_________________{ //LINE-1
a = a + x;
}
};
class Test2 : public Test1{
int b = 20;
public:
void show(){
cout << b << " ";
}
};
void fun(const Test2 &t, int x){
Test2 &u = _________________(t); //LINE-2
u.show();
Test1 &v = ___________________(u); //LINE-3
v = x;
v.show();
}
int main(){
Test2 t1;
int x;
cin >> x;
fun(t1, x);
return 0;
}
Public 1
Input: 4
Output: 20 14
Public 2
Input: 9
Output: 20 19
11
Private 1
Input: 15
Output: 20 25
Answer:
LINE-1: void operator=(int x)
LINE-2: const cast<Test2&>
LINE-3: reinterpret cast<Test1&>
Explanation:
As per the function fun(), we need to overload the operator equal to for the class Test1 at
LINE-1 so that the assignment v = x will be valid. It can be done as void operator=(int
x).
To call a non-constant function show() 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<Test2&>.
Casting between two unrelated classes at LINE-3 can be done as reinterpret cast<Test1&>.
12
Question 2
Consider the following program with the following instructions.
• Fill in the blank at LINE-2 to complete assignment operator overload function signature.
• Fill in the blank at LINE-3 to complete integer cast operator overload function signature.
The program must satisfy the sample input and output. Marks: 3
#include<iostream>
using namespace std;
class StringClass{
int *arr;
int n;
public:
StringClass(int k) : _________________________{} //LINE-1
_______________________{ //LINE-2
return arr[--n];
}
______________________________________(int &k){ //LINE-3
int t;
for(int j = 0; j < k; j++){
cin >> t;
this->arr[j] = t;
}
return *this;
}
};
int main(){
int k;
cin >> k;
StringClass str(k);
str = k;
for(int i = 0; i < k; i++)
cout << static_cast<int>(str) << " ";
return 0;
}
Public 1
Input: 3
1 3 5
Output: 5 3 1
Public 2
Input: 4
5 6 4 8
Output: 8 4 6 5
13
Private
Input: 6
1 2 3 4 5 7
Output: 7 5 4 3 2 1
Answer:
LINE-1: n(k), arr(new int(n))
LINE-2: operator int()
LINE-3: StringClass operator=
Explanation:
The initialization of the data-members at LINE-1 can be done as:
n(k), arr(new int(k))
At LINE-2, we overload type-casting operator for the statement static cast〈int〉(str) as:
operator int()
At LINE-3, we overload operator= for the statement str = k; as:
StringClass operator=(int& k)
14
Question 3
Consider the following program. Fill in the blanks as per the instructions given below:
#include<iostream>
using namespace std;
class B {
public:
B(int i) { cout << 50 * i << " "; }
B() { cout << 1 << " "; }
};
class D1 : ________________ { //LINE-1
public:
D1(int i);
};
class D2 : _________________ { //LINE-2
public:
D2(int i);
};
class D3 : __________________ { //LINE-3
public:
D3(int i);
};
class DD : ______________________________ { //LINE-4
public:
DD (int i) : D1(i), D2(i), D3(i) {
cout << 2 * i << " ";
}
};
D1::D1(int i) : B(i) {
cout << 5 * i << " ";
}
D2::D2(int i) : B(i) {
cout << 4 * i << " ";
}
D3::D3(int i) : B(i) {
cout << 3 * i << " ";
}
int main() {
int i = 0;
cin >> i;
DD dd(i);
return i;
}
Public 1
Input: 2
Output: 1 8 10 6 4
15
Public 2
Input: 3
Output: 1 12 15 9 6
Private
Input: 5
Output: 1 20 25 15 10
Answer:
LINE-1: virtual public B
LINE-2: virtual public B
LINE-3: virtual public B
LINE-4: public D2, public D1, public D3
Explanation:
If we observe the test-cases, the parametrized constructor is never called for the base class,
which implies all the derived classes have virtually inherited the base class. Therefore, the
blanks at LINE-1, LINE-2 and LINE-3 all have to be filled with: virtual public B The
order for invocation of the base class constructors depends on the order of inheritance. Again
from the test-cases it can be observed the sequence of inheritance at LINE-4 must be: public
D2, public D1, public D3
16