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

Assignment - 5 Solution

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

Assignment - 5 Solution

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

Programming in Modern C++: Assignment Week 5

Total Marks : 25

Partha Pratim Das


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

August 13, 2024

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

#include <iostream>

using namespace std;

class Base {
protected:
int number;
static int counter;

public:
Base() {
number = ++counter;
cout << number << "-" << counter << ", ";
}
};

class Derived1 : public Base {


public:
Derived1() {
++counter;
cout << counter << ", ";
}
};

class Derived2 : public Derived1 {


public:
Derived2() {
++counter;
cout << counter << ", ";
}
};

int Base::counter = 0;

1
int main() {
Derived2 dObj[2];
return 0;
}

What will be the output?

a) 1, 2, 3

b) 1, 2, 3-3, 1, 2, 3-3,

c) 1, 2, 3-3, 4, 5, 6-6,

d) 1-1, 2, 3, 4-4, 5, 6,

Answer: d)
Explanation:
When we create an object, all the constructors of the class hierarchy get executed in top-down
order. Since we create 2 objects of Derived2 type. For the first object, class Base prints
1-1, class Derived1 prints 2 and class Derived2 prints 3. For the second object, class
Base prints 4-4, class Derived1 prints 5 and class Derived2 prints 6.

2
Question 2
Consider the following code segment. [MCQ, Marks 1]
#include <iostream>

using namespace std;

class Alpha {
public:
Alpha() {
cout << "A ";
}

~Alpha() {
cout << "-A ";
}
};

class Beta : public Alpha {


public:
Beta() {
cout << "B ";
}

~Beta() {
cout << "-B ";
}
};

class Gamma : public Alpha {


Beta b;

public:
Gamma() {
cout << "C ";
}

~Gamma() {
cout << "-C ";
}
};

int main() {
Gamma g1;
return 0;
}

What will be the output?


a) A B C -C -B -A

b) A A B C -C -A -A

3
c) A C -C -A

d) A A B C -C -B -A -A

Answer: d)
Explanation:
When an object of class Gamma is being instantiated, the constructor of class Alpha is called,
which will print ”A” first. Then the data member of class Gamma is created, which will again
call the constructor of class Alpha and print ”A”, then print ”B” from the constructor of class
Beta. Finally, ”C” is printed from the constructor of class Gamma. After the end of the main()
function, the reverse of the already printed sequence will be printed from the destructors of
the classes. So, the answer is (d).

4
Question 3
Consider the following code segment. [MCQ, Marks 2]
#include <iostream>

using namespace std;

class Vehicle {
public:
Vehicle() {
cout << "Vehicle created, ";
}

~Vehicle() {
cout << "Vehicle destroyed, ";
}
};

class Car : public Vehicle {


public:
Car() {
cout << "Car created, ";
}

~Car() {
cout << "Car destroyed, ";
}
};

class Bike : public Vehicle {


public:
Bike() {
cout << "Bike created, ";
}

~Bike() {
cout << "Bike destroyed, ";
}
};

class SportsCar : public Car {


Bike b;

public:
SportsCar() {
cout << "SportsCar created, ";
}

~SportsCar() {
cout << "SportsCar destroyed, ";
}
};

5
int main() {
SportsCar sc;
return 0;
}

What will be the output?

a) Vehicle created, Car created, Vehicle created, Bike created, SportsCar created,
SportsCar destroyed, Bike destroyed, Vehicle destroyed, Car destroyed, Vehicle
destroyed,

b) Vehicle created, Car created, SportsCar created, Vehicle created, Bike created,
Bike destroyed, Vehicle destroyed, SportsCar destroyed, Car destroyed, Vehicle
destroyed,

c) Vehicle created, Car created, SportsCar created, Bike created, Bike destroyed,
SportsCar destroyed, Car destroyed, Vehicle destroyed,

d) Vehicle created, Car created, SportsCar created, Bike created, Vehicle destroyed,
Car destroyed, SportsCar destroyed, Bike destroyed,

Answer: a)
Explanation:
A constructor of the derived class must first call the constructors of the base classes to construct
the base class instances of the derived class.
The destructor of the derived class must call the destructor of the base classes to destruct the
base class instances of the derived class.
Thus, to instantiate an object of class SportsCar, it first calls the constructor of class
Vehicle which prints Vehicle created. Then the constructor of class Car which prints
Car created. However, to create an object of SportsCar, an object of class Bike needs to
be instantiated. The creation of the Bike object first calls the constructor of class Vehicle
which prints Vehicle created, and then the constructor of class Bike which prints Bike
created. Finally, the constructor of SportsCar is called which prints SportsCar created.
Similarly, the invocation of the destructors takes place in the exact reverse order.

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

#include <iostream>

using namespace std;

class Instrument {
public:
void play() {
cout << "Instrument::play()";
}

void play(int volume) {


cout << "Instrument::play(int)";
}
};

class Guitar : public Instrument {


public:
void play() {
cout << "Guitar::play()";
}

void play(int volume) {


cout << "Guitar::play(int)";
}
};

int main() {
Guitar g;

______________________; // LINE-1

return 0;
}

Choose the appropriate option to fill in the blank at LINE-1 such that the output of the code
becomes Instrument::play().

a) g.play()

b) Instrument::play()

c) g.Instrument::play()

d) Instrument::g.play()

Answer: c)
Explanation:
We can access a base class function using the scope resolution operator even if it is hidden by
a derived class function. Hence, c) is the correct option.

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

#include <iostream>

using namespace std;

int value = 5;

class Parent {
protected:
int value;

public:
Parent() : value(15) {}

~Parent() {}
};

class Child : public Parent {


protected:
int value;

public:
Child() : value(25) {}

~Child() {}

void display() {
cout << _____________________ ; // LINE-1
}
};

int main() {
Child c;
c.display();
return 0;
}

Choose the appropriate option(s) to fill in the blank at LINE-1 such that the output becomes
25 15 5

a) this->value << " " << Parent::value << " " << value

b) Child::value << " " << Parent::value << " " << value

c) value << " " << Parent::value << " " << ::value

d) Child::value << " " << Parent::value << " " << ::value

Answer: c), d)
Explanation:
Since value = 25 is in the scope of class Child which is also the local scope for the function

8
display(), value can be accessed by writing Child::value or just by value.
Since value = 15 is in the scope of class Parent, it can be accessed by writing Parent::value.
Since value = 5 is in the global scope, it can be accessed by writing ::value. So option c)
and d) both are correct.

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

#include <iostream>

using namespace std;

int globalVar = 5;

class MyClass {
int memberVar;

public:
MyClass(int memberVar_ = 0) : memberVar(++memberVar_) { // LINE-1
++globalVar;
}

~MyClass() {
memberVar = 0;
globalVar = 0;
}

void print() {
cout << "memberVar = " << memberVar << ", globalVar = " << globalVar << endl;
}
};

void test() {
MyClass obj;
obj.print();
}

int main() {
MyClass obj;
test();
obj.print();
return 0;
}

What will be the output?

a) memberVar = 6, globalVar = 7
memberVar = 1, globalVar = 8

b) memberVar = 6, globalVar = 8
memberVar = 1, globalVar = 0

c) memberVar = 1, globalVar = 7
memberVar = 2, globalVar = 8

d) memberVar = 1, globalVar = 7
memberVar = 1, globalVar = 0

10
Answer: d)
Explanation:
The statement MyClass obj; in main(), calls the constructor at LINE-1 which makes memberVar
= 1 and globalVar = 6.
Then the statement MyClass obj; in test(), calls the constructor at LINE-1 which makes
memberVar = 1 and globalVar = 7.
Then the statement obj.print(); in test() prints memberVar = 1, globalVar = 7.
As the function test() returns, the destructor for the local object obj would be called, which
makes memberVar = 0 and globalVar = 0.
Finally, the statement obj.print(); in main() prints memberVar = 1, globalVar = 0.

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

#include <iostream>

using namespace std;

class Vehicle {
private:
int reg_no;
string type;

public:
Vehicle(int reg_no_, string type_)
: reg_no(reg_no_), type(type_) {}

void showDetails() {
cout << reg_no << ":" << type << ":";
}
};

class Car : private Vehicle {


private:
int owner_id;
string owner_name;

public:
Car(int owner_id_, string owner_name_, int reg_no_, string type_)
: owner_id(owner_id_),
owner_name(owner_name_),
Vehicle(reg_no_, type_) {}

void showDetails() {
Vehicle::showDetails(); // LINE-1
cout << owner_id << ":" << owner_name;
}
};

int main() {
Car* carObj = new Car(101, "Rahul", 12345, "Sedan");
display(carObj); // LINE-2
delete carObj;
return 0;
}

What will be the output/error?

a) 12345:Sedan:

b) 12345:Sedan:101

c) compiler error at LINE-1: Vehicle is an inaccessible base of Car

12
d) compiler error at LINE-2: ‘display’ was not declared in this scope

Answer: d)
Explanation: Compilers will not convert a derived (Car) class object into a base (Vehicle)
class object if the inheritance relationship is private. As the display() function takes a
parameter of type class Vehicle* and we are passing a parameter of class Car object, it will
give a compilation error as inaccessible base.

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

#include <iostream>

using namespace std;

class Base {
public:
Base() {}

~Base() {}

private:
Base(const Base& obj) {}

Base& operator=(const Base&) {}


};

class Derived : public Base {


int data;

public:
Derived() {}

Derived(const int& data_) : data(data_) {}

void print() {
cout << data << " ";
}
};

int main() {
Derived d1(30);
Derived d2(40);
d1 = d2;
d1.print();
d2.print();
return 0;
}

What will be the output/error?

a) 40 30

b) 40 40

c) Compiler error: ’Base& operator=(const Base&)’ is private

d) Compiler error: ’Base(const Base& obj)’ is private

Answer: c)
Explanation: Since class Derived inherits class Base where the copy constructor and

14
assignment operator function are both private, it prevents the free copy constructor and free
assignment operator function from being added to the Derived class. As a result, when d1 =
d2; invokes the assignment operator function, the call fails.

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

#include <iostream>

using namespace std;

class X {
public:
int x;
};

class Y : protected X {
public:
int y;
};

class Z : public Y {
public:
int z;

Z(int x_, int y_, int z_) {


x = x_; // LINE-1
y = y_;
z = z_;
}
};

int main() {
Z zObj(10, 20, 30);
cout << zObj.x << " "; // LINE-2
cout << zObj.y << " "; // LINE-3
cout << zObj.z;
return 0;
}

What will be the output/error(s)?

a) 10 20 30

b) compiler error at LINE-1: X::x is not accessible

c) compiler error at LINE-2: X::x is not accessible

d) compiler error at LINE-3: Y::y is not accessible

Answer: c)
Explanation:
The inheritance relationship between X and Y is protected. Thus, x becomes protected in
class Y. The inheritance relationship between Y and Z is public. Thus, y remains public in
class Y, but x remains protected in class Z. As a result, x in class Z becomes invisible to
the main() function. Hence, the correct answer is c).

16
Programming Questions

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

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

• at LINE-2 to call displayContact(), such that it will satisfy the given test cases.

#include<iostream>
using namespace std;

class Contact {
private:
int phone_number;
string email;
public:
Contact(int phone_number_, string email_) : phone_number(phone_number_),
email(email_){}
void displayContact(){
cout << "Phone: " << phone_number << endl;
cout << "Email: " << email << endl;
}
};

class Employee : private Contact {


private:
int emp_id;
string emp_name;
public:
Employee(int emp_id_, string emp_name_, int phone_number_, string email_)
: ____________________{} // LINE-1
__________________ // LINE-2
void display(){
cout << "ID: " << emp_id << endl;
cout << "Name: " << emp_name << endl;
}
};
int main(){
int id, phone;
string name, email;
cin >> id >> name;
cin >> phone >> email;
Employee e(id, name, phone, email);
e.display();
e.displayContact();
return 0;
}

17
Public 1
Input:
101 9876543210
Alice [email protected]
Output:
ID: 101
Name: Alice
Phone: 9876543210
Email: [email protected]

Public 2
Input:
102 1234567890
Bob [email protected]
Output:
ID: 102
Name: Bob
Phone: 1234567890
Email: [email protected]

Private
Input:
103 1112223333
Charlie [email protected]
Output:
ID: 103
Name: Charlie
Phone: 1112223333
Email: [email protected]

Answer:
LINE-1: emp id(emp id ), emp name(emp name ), Contact(phone number , email )
LINE-2: using Contact::displayContact;
Explanation:
At LINE-1, the data members from Employee must be initialized as:
emp id(emp id ), emp name(emp name ), and the data members from Contact must be ini-
tialized as: Contact(phone number , email ) Although the function displayContact() is
public in Contact, it becomes private in Employee due to private inheritance. So displayContact()
becomes inaccessible using the Employee object. In order to call the displayContact() func-
tion using the Employee object, at LINE-2 we must add:
using Contact::displayContact;

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

• at LINE-1 and LINE-3 with the appropriate inheritance statement,

• at LINE-2 and LINE-4 with the appropriate initialization lists, such that it will satisfy
the given test cases.

#include <iostream>

using namespace std;

class Appliance {
protected:
int power;

public:
Appliance(int p) : power(p) {}

friend ostream& operator<<(ostream& os, const Appliance& a);


};

class WashingMachine : ________________{ // LINE-1


protected:
int drum_size;

public:
WashingMachine(int p, int ds) : __________ {} // LINE-2

friend ostream& operator<<(ostream& os, const WashingMachine& wm);


};

class Refrigerator : __________ { // LINE-3


protected:
int capacity;

public:
Refrigerator(int p, int c) : ___________{} // LINE-4

friend ostream& operator<<(ostream& os, const Refrigerator& r);


};

ostream& operator<<(ostream& os, const Appliance& a) {


os << "Power: " << a.power << "W" << endl;
return os;
}

ostream& operator<<(ostream& os, const WashingMachine& wm) {


os << "Power: " << wm.power << "W, Drum size: " << wm.drum_size << "L" << endl;
return os;
}

19
ostream& operator<<(ostream& os, const Refrigerator& r) {
os << "Power: " << r.power << "W, Capacity: " << r.capacity << "L" << endl;
return os;
}

int main() {
int a, b, c, d, e;
cin >> a >> b >> c >> d >> e;
Appliance appliance(a);
WashingMachine wm(b, c);
Refrigerator fridge(d, e);
cout << appliance << wm << fridge;
return 0;
}

Public 1
Input:
500 600 50 700 200
Output:
Power: 500W
Power: 600W, Drum size: 50L
Power: 700W, Capacity: 200L

Public 2
Input:
300 400 35 450 150
Output:
Power: 300W
Power: 400W, Drum size: 35L
Power: 450W, Capacity: 150L

Private
Input:
1000 850 60 950 250
Output:
Power: 1000W
Power: 850W, Drum size: 60L
Power: 950W, Capacity: 250L

Answer:
LINE-1: public Appliance
LINE-2: drum size(ds), Appliance(p)
LINE-3: public Appliance
LINE-4: Appliance(p), capacity(c)
Explanation:
Since WashingMachine and Refrigerator both inherit class Appliance, at LINE-1 and
LINE-3 the inheritance statement must be public Appliance.

20
At LINE-2, the initialization list must be:
drum size(ds), Appliance(p)
and at LINE-4, the initialization list must be:
Appliance(p), capacity(c)

21
Question 3
Marks: 3
Consider the following program. Fill in the blanks as per the instructions given below:
• at LINE-1, LINE-2 and LINE-3 with initialization list,
• at LINE-4, LINE-5 and LINE-6 with function definitions, such that it will satisfy the
given test cases.

#include<iostream>
using namespace std;

class X {
int x;
public:
X(int _x = 0);
int getSum();
};

class Y : public X {
int y;
public:
Y(int _x = 0, int _y = 0);
int getSum();
};

class Z : public Y {
int z;
public:
Z(int _x = 0, int _y = 0, int _z = 0);
int getSum();
};

X::X(int _x) : _______________________________ {} //LINE-1


Y::Y(int _x, int _y) : _______________________ {} //LINE-2
Z::Z(int _x, int _y, int _z) : _______________ {} //LINE-3
int X::getSum(){ _____________________________ } //LINE-4
int Y::getSum(){ _____________________________ } //LINE-5
int Z::getSum(){ _____________________________ } //LINE-6

int main(){
int a, b, c;
cin >> a >> b >> c;
X xObj(a);
Y yObj(a, b);
Z zObj(a, b, c);
cout << xObj.getSum() << ", " << yObj.getSum() << ", " << zObj.getSum();
return 0;
}

Public 1
Input: 10 20 30

22
Output: 10, 30, 60

Public 2
Input: 10 -10 10
Output: 10, 0, 10

Private
Input: 10 20 -10
Output: 10, 30, 20

Answer:
LINE-1: x( x)
LINE-2: X( x), y( y)
LINE-3: Y( x, y), z( z)
LINE-4: return x;
LINE-5: return X::getSum() + y;
LINE-6: return Y::getSum() + z;
Explanation:
The initialization lists at LINE-1, LINE-2 and LINE-3 are as follows:
LINE-1: x( x)
LINE-2: X( x), y( y)
LINE-3: Y( x, y), z( z)
The definition of the getSum() functions at LINE-4, LINE-5 and LINE-6 are as follows:
LINE-4: return x;
LINE-5: return X::getSum() + y;
LINE-6: return Y::getSum() + z;

23

You might also like