Self-test 3:
Constructors & Destructors
-
Which of the followings is/are automatically and unconditionally added to every class, if we do not write our own?
- Copy Constructor.
- Assignment Operator.
- A constructor without any parameter.
- A and B only.
- All of the above.
SolutionD is correct. In C++, if we do not write our own copy constructor and assignment operator for a class, the compiler automatically creates them. The default constructor will also be created by the compiler but only under the situation when no constructors of any kind are defined for a class.
-
When a copy constructor may be called?
- When an object of the class is returned by value.
- When an object of the class is passed (to a function) by value as an argument.
- When an object is constructed based on another object of the same class
- All of the above.
SolutionD is correct. Conceptually a copy constructor may be called in following cases:- When an object of the class is returned by value.
- When an object of the class is passed (to a function) by value as an argument.
- When an object is constructed based on another object of the same class.
- When compiler generates a temporary object.
-
Which, if any, of the following statements are not true? Why?
- A class must provide at least one constructor.
- A default constructor is a constructor with no formal parameters in its parameter list.
- If there are no meaningful default values for a class, the class should not provide a default constructor.
- We can have more than one constructor in a class, as long as each has a different list of arguments.
SolutionA, B and C are not true. A is not true; even if no constructor of any kinds are provided, the compiler still will give you a default constructor. B is not true (this is a tricky question); e.g., Word(int f = 0, char* s = nullptr) { frequency = f; str = s; } is still a default constructor though its parameter list consists of 2 variables because it may be called with no arguments due to the use of defaults values for both formal parameters. C is not true, constructor may assign default values to object, indicating that the object has invalid initial values.
-
Which of the following statements is/are incorrect?
- Constructor can be called explicitly.
- Constructor can be called implicitly.
- Destructor is usually called implicitly.
- Constructor and destructor functions are not called at all as they are always inlined.
SolutionD is incorrect. Constructors and destructors can be both inline functions or non-inline functions.
-
What is the output of following program?
#include<iostream> using namespace std; class Point { Point() { cout << "Constructor called"; } }; int main() { Point x; return 0; }
- Compilation error.
- Runtime error.
- Constructor called.
- None of the above.
SolutionA is correct. By default all members of a class are private. Since no access specifier is there for Point( ), it is private and it can't be called outside the class when x is constructed in main( ). So the compiler will issue an error message something like "calling a private constructor of class Point".
-
What is the output of following program?
#include<iostream> using namespace std; class X { public: int x; }; int main() { X a = { 10 }; X b = a; cout << a.x << " " << b.x; return 0; }
- Compilation error
- 10 followed by Garbage Value
- 10 10
- 10 0
SolutionC is correct. The following: "X a = {10};" may look like an error, but it works fine. Like structures, class objects with only public data members can be initialized using the { } syntax. The line "X b = a;" calls the copy constructor and is same as "X b(a);". Please note that, if we don't write our own copy constructor, then compiler creates a default copy constructor which does the default memberwise assignment.
-
What is the output of following program?
#include<iostream> using namespace std; class Test { public: Test() { cout << "Hello from Test() "; } } a; int main() { cout << "Main Started "; return 0; }
- Main Started
- Main Started Hello from Test()
- Hello from Test() Main Started
- Compilation error: Global objects are not allowed
SolutionC is correct. There is a global object a which is constructed before the main functions starts. So the constructor for a is called first, then main( ) execution begins.
-
What is the output of following program?
#include<iostream> using namespace std; class Point { int x; public: Point(int x) { this->x = x; } Point(const Point p) { x = p.x;} int getX() { return x; } }; int main() { Point p1(10); Point p2 = p1; cout << p2.getX(); return 0; }
- 10
- Compilation error: p must be passed by reference
- Garbage value
- None of the above
SolutionB is correct. Objects must be passed by reference in copy constructors. i.e. Copy constructor of class X must have the following signature: X::X(const X& copiee). It cannot be X::X(const X copiee) otherwise it requires copiee to be passed by value to the copy constructor, which in turn will ask for a copy constructor to make the copy, ... resulting in an infinite recursion!
-
What is the output of following program?
#include<iostream> using namespace std; class Test { private: int x; public: Test(int i) { x = i; cout << "conversion "; } }; int main() { Test t(20); t = 30; return 0; }
- Compilation error
- conversion conversion
- conversion
- None of the above
SolutionB is correct. If a class has a constructor which can be called with a single argument, then the constructor is a conversion constructor because it allows automatic conversion of the argument object to the class' object. A conversion constructor can be called anywhere when the type of the single argument is assigned to the object. In the above code, at the line "t = 30", 30 is converted automatically to a Test object and default assignment is then performed to assign 30 to t.
-
What is the output of following program?
#include<iostream> using namespace std; int i; class A { public: ~A() { i = 10; } }; int foo() { i = 3; A x; return i; } int main() { cout << foo() << endl; return 0; }
- 0
- 3
- 10
- None of the above
SolutionB is correct. While returning from a function, destructors are the last methods to be executed. The destructor for the object "x" is called after the value of i is copied to the return value of the function. So, before destructor could change the value of i to 10, the current value of i gets copied to the main( ) function already.