C++_Assignmnet-7
C++_Assignmnet-7
Total Marks : 25
Question 1
Consider the following code segment. [MSQ, Marks 2]
#include <iostream>
using namespace std;
class Employee {
string name ;
public:
Employee(string _name = "unknown") : name(_name) {}
void update(string na) const{
( _____________________________ )->name = na; //LINE-1
}
void showInfo() const {
cout << "Name: " << name;
}
};
int main(void) {
const Employee e("Sam");
e.update("Sameer");
e.showInfo();
return 0;
}
Fill in the blank at LINE-1 such that the program will print Name: Sameer.
d) (Employee*)(this)
Answer: a), d)
Explanation:
The statement const Employee e("Sam"); defines e as a constant object. To modify its
data-members the constant-ness of the object need to be removed. This can be done either by
const cast (in option a) or casting constant this pointer to Employee* type (in option d).
1
Question 2
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
using namespace std;
int incr(int* ptr){
return ++(*ptr);
}
int main(void) {
int x = 5;
const int *ptr = &x;
x = incr(_________________________); //LINE-1
cout << x;
return 0;
}
Fill in the blank at LINE-1 such that the program will print 6.
a) const cast<int*>(ptr)
b) static cast<int*>(ptr)
c) dynamic cast<int*>(ptr)
d) reinterpret cast<int*>(ptr)
Answer: a)
Explanation:
The function incr() modify the value of *ptr and the modified value is returned as return by
value. But, in main() function ptr is declared as const int *ptr;. Hence, the constant-ness
of *ptr has to be removed, which can be done using const cast. So, a) is the correct option.
2
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include<iostream>
using namespace std;
class A1{
public:
virtual void f() {}
void g() {}
};
class A2 : public A1{
public:
virtual void g() {}
void h() {}
virtual void i();
};
class A3 : public A2{
public:
void g() {}
virtual void h() {}
};
What will be the virtual function table for the class A3?
a) A1::f(A1* const)
A3::g(A3* const)
A3::h(A3* const)
A2::i(A2* const)
b) A1::f(A1* const)
A2::g(A2* const)
A3::h(A3* const)
A2::i(A2* const)
c) A1::f(A1* const)
A2::g(A2* const)
A2::h(A2* const)
A3::i(A3* const)
d) A1::f(A1* const)
A2::g(A2* const)
A3::h(A3* const)
A3::i(A3* const)
Answer: a)
Explanation:
All four functions are virtual in the class A3. So, there will be four entries in virtual function
table.
Now function f() is not overridden in class A2 and A3. So, the entry for function f() in the
virtual function table of class A3 will be A1::f(A1* const).
The function g() is virtual from class A2 and is overridden in class A3. So, the entry for
function g() in VFT of class A3 will be A3::g(A3* const).
The function h() is declared as virtual in class A3. So, the entry for function h() in VFT of
class A3 will be A3::h(A3* const).
3
Question 4
How many virtual tables will be created for the following classes. [MCQ, Marks 2]
a) 1
b) 2
c) 3
d) 4
Answer: b)
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). Here, only class B and D will have VFTs.
4
Question 5
Consider the following code segment. [MCQ, Marks 2]
class st1 { };
class st2 { };
st1* s1 = new st1;
st2* s2 = new st2;
Answer: c)
Explanation:
On each option, there is an attempt to cast from st1* to st2*, 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.
5
Question 6
Consider the following code segment. [MSQ, 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());
return 0;
}
a) 0101
b) 1010
c) 0111
d) 1011
Answer: a)
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.
6
Question 7
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class Base{
public:
virtual void f(){
cout << "Base ";
}
};
class Derived : public Base{
public:
virtual void f(){
cout << "Derived ";
}
};
int main() {
Base obb;
Derived obd;
try{
Base& ra1 = static_cast<Base&>(obd); //LINE-1
ra1.f();
Base& ra2 = dynamic_cast<Base&>(obd); //LINE-2
ra2.f();
Derived& rb1 = static_cast<Derived&>(obb); //LINE-3
rb1.f();
Derived& rb2 = dynamic_cast<Derived&>(obb); //LINE-4
rb2.f();
}
catch(exception& e){
cout << e.what();
}
return 0;
}
Answer: c)
Explanation:
The statement at LINE-1, is having upcasting which may be done using static cast. Hence,
ra1.f(); prints Derived.
The statement at LINE-2, is having upcasting which may be done using dynamic cast. Hence,
rb1.f(); prints Derived.
The statement at LINE-3, is having downcasting which may be done using static cast.
Hence, ra2.f(); prints Base.
7
The statement at LINE-4, is having downcasting which cannot be done using dynamic cast.
Hence, it throws an exception and prints std::bad cast.
8
Question 8
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 = static_cast<A*>(&objB); //LINE-1
pA == NULL ? cout << "cast-1 invalid:" : cout << "cast-1 valid:";
B* pB = static_cast<B*>(pA); //LINE-2
pB == NULL ? cout << "cast-2 invalid:" : cout << "cast-2 valid:";
C* pC = dynamic_cast<C*>(new A); //LINE-3
pC == NULL ? cout << "cast-3 invalid:" : cout << "cast-3 valid:";
pC = dynamic_cast<C*>(&objB); //LINE-4
pC == NULL ? cout << "cast-4 invalid" : cout << "cast-4 valid";
return 0;
}
Answer: a)
Explanation:
The type-casting at LINE-1 is valid as it is an upcasting.
At LINE-2, though it is a downcasting, it is allowed as the pointer pB points to the same type
of object (which of type B).
At LINE-3, the downcasting is invalid as the pointer pC points to parent type of object (which
is of type 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.
9
Question 9
Consider the code segment given below. [MCQ, Marks 2]
#include <iostream>
using namespace std;
class B{
int a;
public:
B(int x) : a(x) {}
int get() { return a; }
void set(int x) { a = x + 1; }
};
class D : public B{
int b;
public:
D(int x, int y) : B(x), b(y) {}
void change(int c){
static_cast<B>(*this).set(c);
b = c+1;
}
void print(){
cout << B::get() << " " << b;
}
};
int main() {
D d(10,20);
d.change(7);
d.print();
return 0;
}
a) 10 8
b) 10 7
c) 7 21
d) 7 20
Answer: a)
Explanation:
As per the change() function definition, static cast operator will create a temporary object
of B class type and assign its data member with the value 7 + 1 = 8. But, actual B class object
data member is not changed. However, the change of D class data member is straightforward.
Hence, the program will print 10 8.
10
Programming Questions
Question 1
Complete the program with the following instructions.
• Fill in the blanks at LINE-2 to complete cast operator overloading function to typecast
to IP1 type.
#include <iostream>
using namespace std;
class IP1 {
int i;
public:
IP1(int ai) : i(ai) {}
int get() const { return i; }
void update() { i *= 10; }
};
class IP2 {
int i;
public:
IP2(int ai) : i(ai) {}
int get() const { return i; }
_________________________________ //LINE-1
_________________________________ //LINE-2
void update() { i *= 20; }
};
int main() {
int i;
cin >> i;
IP1 a(i+2);
IP2 b(i);
const IP2 &r = static_cast<IP2>(a);
a.update();
cout << a.get() << ":";
cout << r.get() << ":";
const IP1 &s = static_cast<IP1>(b);
b.update();
cout << b.get() << ":";
cout << s.get() << ":";
return 0;
}
Public 1
Input: 2
Output: 40:4:40:2:
11
Public 2
Input: 5
Output: 70:7:100:5:
Private 1
Input: 15
Output: 170:17:300:15:
Answer:
LINE-1: IP2(IP1& a) : i(a.get()) {}
LINE-2: operator IP1() { return IP1(i); }
Explanation:
static cast can explicitly call a single-argument constructor or a conversion operator (that
is, User-Defined Cast) to handle the casting between two unrelated classes. Here both are
present.
12
Question 2
Consider the following program with the following instructions.
• Fill in the blank at LINE-1 to complete assignment operator overload function header.
• Fill in the blanks at LINE-2 and LINE-3 to complete statements with the appropriate
casting operator.
The program must satisfy the sample input and output. Marks: 3
#include<iostream>
using namespace std;
class myClassA{
int a = 5;
public:
void print(){
cout << a << " ";
}
};
class myClassB{
int b = 10;
public:
void print(){
cout << b;
}
___________________{ //LINE-1
b = b * x;
}
};
void fun(const myClassA &t){
int x;
cin >> x;
myClassA &u = _________________________(t); //LINE-2
u.print();
myClassB &v = ____________________________(u); //LINE-3
v = x;
v.print();
}
int main(){
myClassA t1;
fun(t1);
return 0;
}
Public 1
Input: 5
Output: 5 25
Public 2
Input: 7
Output: 5 35
13
Private
Input: 100
Output: 5 500
Answer:
LINE-1: void operator=(int x)
LINE-2: const cast<myClassA&>
LINE-3: reinterpret cast<myClassB&>
Explanation:
As per the function fun(), we need to overload assignment operator for the class myClassB 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 print(.) using a constant object reference u, we need to cast
the reference to a non-const reference. So, LINE-2 will be filled as const cast<myClassA&>.
Casting between two unrelated classes at LINE-3 can be done as reinterpret cast<myClassB&>.
14
Question 3
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, "Welcome ");
strcat(t_str, _str);
return t_str;
}
};
int main(){
char s[15];
cin >> s;
String st = static_cast<String>(s);
cout << static_cast<char*>(st);
return 0;
}
Public 1
Input: Amal
Output: Welcome Amal
Public 2
Input: Som
Output: Welcome Som
Private
Input: Sir
Output: Welcome Sir
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. In can be done as operator char*().
15