Saturday, 27 August 2011

C++ Interview Questions and Answers (3)

C++ Interview Questions and Answers (3)

virtual

Q: What is virtual function?
A: When derived class overrides the base class method by redefining the same function, then if
client wants to access redefined the method from derived class through a pointer from base class
object, then you must define this function in base class as virtual function.
class parent
{
void Show()
{
cout << "i'm parent" << endl; } }; class child: public parent { void Show() { cout << "i'm child" << endl; } }; parent * parent_object_ptr = new child; parent_object_ptr->show() // calls parent->show()
now we goto virtual world...
class parent
{
virtual void Show()
{
cout << "i'm parent" << endl; } }; class child: public parent { void Show() { cout << "i'm child" << endl; } }; parent * parent_object_ptr = new child; parent_object_ptr->show() // calls child->show()

Q: What is a "pure virtual" member function?
A: The abstract class whose pure virtual method has to be implemented by all the classes which
derive on these. Otherwise it would result in a compilation error. This construct should be used
when one wants to ensure that all the derived classes implement the method defined as pure
virtual in base class.

Q: How virtual functions are implemented C++?
A: Virtual functions are implemented using a table of function pointers, called the vtable. There
is one entry in the table per virtual function in the class. This table is created by the constructor
of the class. When a derived class is constructed, its base class is constructed _rst which creates
the vtable. If the derived class overrides any of the base classes virtual functions, those entries in
the vtable are overwritten by the derived class constructor. This is why you should never call
virtual functions from a constructor: because the vtable entries for the object may not have
been set up by the derived class constructor yet, so you might end up calling base class
implementations of those virtual functions


Q: What is pure virtual function? or what is abstract class?
A: When you de_ne only function prototype in a base class without implementation and do the
complete implementation in derived class. This base class is called abstract class and client won't
able to instantiate an object using this base class. You can make a pure virtual function or
abstract class this way..
class Boo
{
void foo() = 0;
}
Boo MyBoo; // compilation error

Q: What is Pure Virtual Function? Why and when it is used?
A: The abstract class whose pure virtual method has to be implemented by all the classes which
derive on these. Otherwise it would result in a compilation error. This construct should be used
when one wants to ensure that all the derived classes implement the method defined as pure
virtual in base class.

Q: How Virtual functions call up is maintained?
A: Through Look up tables added by the compile to every class image. This also leads to
performance penalty.

Q: What is a virtual destructor?
A: The simple answer is that a virtual destructor is one that is declared with the virtual attribute.
The behavior of a virtual destructor is what is important. If you destroy an object through a caller
or reference to a base class, and the base-class destructor is not virtual, the derived-class
destructors are not executed, and the destruction might not be complete.


Inheritance

Q: What is inheritance?
A: Inheritance allows one class to reuse the state and behavior of another class. The derived class
inherits the properties and method implementations of the base class and extends it by overriding
methods and adding additional properties and methods.

Q: When should you use multiple inheritance?
A:There are three acceptable answers:- "Never,""Rarely," and "When the problem domain
cannot be accurately modeled any other way." Consider an Asset class, Building class, Vehicle
class, and CompanyCar class. All company cars are vehicles. Some company cars are assets
because the organizations own them. Others might be leased. Not all assets are vehicles. Money
accounts are assets. Real estate holdings are assets. Some real estate holdings are buildings. Not
all buildings are assets. Ad infinitum. When you diagram these relationships, it becomes
apparent that multiple inheritance is a likely and intuitive way to model this common problem
domain. The applicant should understand, however, that multiple inheritance, like a chainsaw, is
a useful tool that has its perils, needs respect, and is best avoided except when nothing else will
do.

Q: Explain the ISA and HASA class relationships. How would you implement each in a class
design?
A: A specialized class "is" a specialization of another class and, therefore, has the ISA
relationship with the other class. This relationship is best implemented by embedding an object
of the Salary class in the Employee class.

Q: When is a template a better solution than a base class?
A: When you are designing a generic class to contain or otherwise manage objects of other
types, when the format and behavior of those other types are unimportant to their containment or
management, and particularly when those other types are unknown (thus, the generality) to the
designer of the container or manager class.


Q: What is multiple inheritance(virtual inheritance)? What are its advantages and disadvantages?
A: Multiple Inheritance is the process whereby a child can be derived from more than one parent
class. The advantage of multiple inheritance is that it allows a class to inherit the functionality of
more than one base class thus allowing for modeling of complex relationships.
The disadvantage of multiple inheritance is that it can lead to a lot of confusion(ambiguity)
when two base classes implement a method with the same name.
Q: What a derived class inherits or doesn't inherit?
A: Inherits:

Every data member defined in the parent class (although such members may not always be
accessible in the derived class!)
Every ordinary member function of the parent class (although such members may not always be
accessible in the derived class!)

The same initial data layout as the base class.

Doesn't Inherit :

The base class's constructors and destructor.

The base class's assignment operator.

The base class's friends

polymorphism

Q: What is Polymorphism??
A: Polymorphism allows a client to treat di_erent objects in the same way even if they were
created from di_erent classes and exhibit di_erent behaviors. You can use implementation
inheritance to achieve polymorphism in languages such as C++ and Java. Base class object's
pointer can invoke methods in derived class objects. You can also achieve polymorphism in C++
by function overloading and operator overloading.

Q: What is problem with Runtime type identification?
A: The run time type identification comes at a cost of performance penalty. Compiler maintains
the class.

Q: What is Polymorphism?
A: Polymorphism allows a client to treat different objects in the same way even if they were
created from different classes and exhibit different behaviors. You can use implementation
inheritance to achieve polymorphism in languages such as C++ and Java. Base class object's
pointer can invoke methods in derived class objects. You can also achieve polymorphism in
C++ by function overloading and operator overloading.

Classes


Q: What is a class?
A: A class is an expanded concept of a data structure: instead of holding only data, it can hold
both data and functions.

Q: What are the differences between a C++ struct and C++ class?
A: The default member and base class access specifies are different. This is one of the
commonly misunderstood aspects of C++. Believe it or not, many programmers think that a C++
struct is just like a C struct, while a C++ class has inheritance, access specifes, member
functions, overloaded operators, and so on. Actually, the C++ struct has all the features of the
class. The only differences are that a struct defaults to public member access and public base
class inheritance, and a class defaults to the private access specified and private base-class
inheritance.

Q: How do you know that your class needs a virtual destructor?
A: If your class has at least one virtual function, you should make a destructor for this class
virtual. This will allow you to delete a dynamic object through a caller to a base class object. If
the destructor is non-virtual, then wrong destructor will be invoked during deletion of the
dynamic object.

Q: What is encapsulation?
A: Containing and hiding Information about an object, such as internal data structures and code.
Encapsulation isolates the internal complexity of an object's operation from the rest of the
application. For example, a client component asking for net revenue from a business object need
not know the data's origin.

Q: What is "this" pointer?
A: The this pointer is a pointer accessible only within the member functions of a class, struct, or
union type. It points to the object for which the member function is called. Static member
functions do not have a this pointer. When a nonstatic member function is called for an
object, the address of the object is passed as a hidden argument to the function. For example, the
following function call
myDate.setMonth( 3 );
can be interpreted this way:
setMonth( &myDate, 3 );
The object's address is available from within the member function as the this pointer. It is legal,
though unnecessary, to use the this pointer when referring to members of the class.

Q: What happens when you make call "delete this;"?
A: The code has two built-in pitfalls. First, if it executes in a member function for an extern,
static, or automatic object, the program will probably crash as soon as the delete statement
executes. There is no portable way for an object to tell that it was instantiated on the heap, so the
class cannot assert that its object is properly instantiated. Second, when an object commits
suicide this way, the using program might not know about its demise. As far as the instantiating
program is concerned, the object remains in scope and continues to exist even though the object

did itself in. Subsequent dereferencing of the pointer can and usually does lead to disaster.
You should never do this. Since compiler does not know whether the object was allocated on the
stack or on the heap, "delete this" could cause a disaster.


Q: What is assignment operator?
A: Default assignment operator handles assigning one object to another of the same class.
Member to member copy (shallow copy)

Q: What are all the implicit member functions of the class? Or what are all the functions which
compiler implements for us if we don't define one?
A:
(a) default ctor
(b) copy ctor
(c) assignment operator
(d) default destructor
(e) address operator

Q: What is a container class? What are the types of container classes?
A: A container class is a class that is used to hold objects in memory or external storage. A
container class acts as a generic holder. A container class has a predefined behavior and a well-
known interface. A container class is a supporting class whose purpose is to hide the topology
used for maintaining the list of objects in memory. When a container class contains a group of
mixed objects, the container is called a heterogeneous container; when the container is holding a
group of objects that are all the same, the container is called a homogeneous container.

Q: What is Overriding?
A: To override a method, a subclass of the class that originally declared the method must declare
a method with the same name, return type (or a subclass of that return type), and same parameter
list.
The definition of the method overriding is:
· Must have same method name.
· Must have same data type.
· Must have same argument list.
Overriding a method means that replacing a method functionality in child class. To imply
overriding functionality we need parent and child classes. In the child class you define the same
method signature as one defined in the parent class.

Q: How do you access the static member of a class?
A: ::

Q: What is a nested class? Why can it be useful?
A: A nested class is a class enclosed within the scope of another class. For example:
// Example 1: Nested class
//
class OuterClass

{
class NestedClass
{
// ...
};
// ...
};
Nested classes are useful for organizing code and controlling access and dependencies. Nested
classes obey access rules just like other parts of a class do; so, in Example 1, if NestedClass is
public then any code can name it as OuterClass::NestedClass. Often nested classes contain
private implementation details, and are therefore made private; in Example 1, if NestedClass
is private, then only OuterClass's members and friends can use NestedClass. When you
instantiate as outer class, it won't instantiate inside class.

Q: What is a local class? Why can it be useful?
A: Local class is a class defined within the scope of a function _ any function, whether a
member function or a free function. For example:
// Example 2: Local class
//
int f()
{
class LocalClass
{
// ...
};
// ...
};
Like nested classes, local classes can be a useful tool for managing code dependencies.
Q: What a derived class can add?
A: New data members

New member functions

New constructors and destructor

New friends
Q: What happens when a derived-class object is created and destroyed?
A: Space is allocated (on the stack or the heap) for the full object (that is, enough space to store
the data members inherited from the base class plus the data members defined in the derived
class itself)

The base class's constructor is called to initialize the data members inherited from the base class

The derived class's constructor is then called to initialize the data members added in the derived
class


The derived-class object is then usable

When the object is destroyed (goes out of scope or is deleted) the derived class's destructor is
called on the object first

Then the base class's destructor is called on the object

Finally the allocated space for the full object is reclaimed

Q: How do I create a subscript operator for a Matrix class?
A: Use operator() rather than operator[].

When you have multiple subscripts, the cleanest way to do it is with operator() rather than with
operator[]. The reason is that operator[] always takes exactly one parameter, but operator() can
take any number of parameters (in the case of a rectangular matrix, two parameters are needed).

For example:


class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double& operator() (unsigned row, unsigned col); subscript operators often come in pairs
double operator() (unsigned row, unsigned col) const; subscript operators often come in pairs
...
~Matrix(); // Destructor
Matrix(const Matrix& m); // Copy constructor
Matrix& operator= (const Matrix& m); // Assignment operator
...
private:
unsigned rows_, cols_;
double* data_;
};

inline
Matrix::Matrix(unsigned rows, unsigned cols)
: rows_ (rows)
, cols_ (cols)
//data_ <--initialized below (after the 'if/throw' statement) { if (rows == 0 || cols == 0) throw BadIndex("Matrix constructor has 0 size"); data_ = new double[rows * cols]; } inline Matrix::~Matrix() { delete[] data_; } inline double& Matrix::operator() (unsigned row, unsigned col) { if (row >= rows_ || col >= cols_)
throw BadIndex("Matrix subscript out of bounds");
return data_[cols_*row + col];
}

inline
double Matrix::operator() (unsigned row, unsigned col) const
{
if (row >= rows_ || col >= cols_)
throw BadIndex("const Matrix subscript out of bounds");
return data_[cols_*row + col];
}
Then you can access an element of Matrix m using m(i,j) rather than m[i][j]:


int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8); ... } Q: Why shouldn't my Matrix class's interface look like an array-of-array? A: Here's what this FAQ is really all about: Some people build a Matrix class that has an operator[] that returns a reference to an Array object (or perhaps to a raw array, shudder), and that Array object has an operator[] that returns an element of the Matrix (e.g., a reference to a double). Thus they access elements of the matrix using syntax like m[i][j] rather than syntax like m(i,j). The array-of-array solution obviously works, but it is less flexible than the operator() approach. Specifically, there are easy performance tuning tricks that can be done with the operator() approach that are more difficult in the [][] approach, and therefore the [][] approach is more likely to lead to bad performance, at least in some cases. For example, the easiest way to implement the [][] approach is to use a physical layout of the matrix as a dense matrix that is stored in row-major form (or is it column-major; I can't ever remember). In contrast, the operator() approach totally hides the physical layout of the matrix, and that can lead to better performance in some cases. Put it this way: the operator() approach is never worse than, and sometimes better than, the [][] approach. The operator() approach is never worse because it is easy to implement the dense, row-major physical layout using the operator() approach, so when that configuration happens to be the optimal layout from a performance standpoint, the operator() approach is just as easy as the [][] approach (perhaps the operator() approach is a tiny bit easier, but I won't quibble over minor nits). The operator() approach is sometimes better because whenever the optimal layout for a given application happens to be something other than dense, row-major, the implementation is often significantly easier using the operator() approach compared to the [][] approach. As an example of when a physical layout makes a significant difference, a recent project happened to access the matrix elements in columns (that is, the algorithm accesses all the elements in one column, then the elements in another, etc.), and if the physical layout is row- major, the accesses can "stride the cache". For example, if the rows happen to be almost as big as the processor's cache size, the machine can end up with a "cache miss" for almost every element access. In this particular project, we got a 20% improvement in performance by changing the mapping from the logical layout (row,column) to the physical layout (column,row). Of course there are many examples of this sort of thing from numerical methods, and sparse matrices are a whole other dimension on this issue. Since it is, in general, easier to implement a sparse matrix or swap row/column ordering using the operator() approach, the operator() approach loses nothing and may gain something it has no down-side and a potential up-side. Use the operator() approach. Q: Should I design my classes from the outside (interfaces first) or from the inside (data first)? A: From the outside! A good interface provides a simplified view that is expressed in the vocabulary of a user. In the case of OO software, the interface is normally the set of public methods of either a single class or a tight group of classes. First think about what the object logically represents, not how you intend to physically build it. For example, suppose you have a Stack class that will be built by containing a LinkedList: class Stack { public: ... private: LinkedList list_; }; Should the Stack have a get() method that returns the LinkedList? Or a set() method that takes a LinkedList? Or a constructor that takes a LinkedList? Obviously the answer is No, since you should design your interfaces from the outside-in. I.e., users of Stack objects don't care about LinkedLists; they care about pushing and popping. Now for another example that is a bit more subtle. Suppose class LinkedList is built using a linked list of Node objects, where each Node object has a pointer to the next Node: class Node { /*...*/ }; class LinkedList { public: ... private: Node* first_; }; Should the LinkedList class have a get() method that will let users access the first Node? Should the Node object have a get() method that will let users follow that Node to the next Node in the chain? In other words, what should a LinkedList look like from the outside? Is a LinkedList really a chain of Node objects? Or is that just an implementation detail? And if it is just an implementation detail, how will the LinkedList let users access each of the elements in the LinkedList one at a time? The key insight is the realization that a LinkedList is not a chain of Nodes. That may be how it is built, but that is not what it is. What it is is a sequence of elements. Therefore the LinkedList abstraction should provide a LinkedListIterator class as well, and that LinkedListIterator might have an operator++ to go to the next element, and it might have a get()/set() pair to access its value stored in the Node (the value in the Node element is solely the responsibility of the LinkedList user, which is why there is a get()/set() pair that allows the user to freely manipulate that value). Starting from the user's perspective, we might want our LinkedList class to support operations that look similar to accessing an array using pointer arithmetic: void userCode(LinkedList& a) { for (LinkedListIterator p = a.begin(); p != a.end(); ++p) std::cout << *p << '\n'; } To implement this interface, LinkedList will need a begin() method and an end() method. These return a LinkedListIterator object. The LinkedListIterator will need a method to go forward, ++p; a method to access the current element, *p; and a comparison operator, p != a.end(). The code follows. The important thing to notice is that LinkedList does not have any methods that let users access Nodes. Nodes are an implementation technique that is completely buried. This makes the LinkedList class safer (no chance a user will mess up the invariants and linkages between the various nodes), easier to use (users don't need to expend extra effort keeping the node-count equal to the actual number of nodes, or any other infrastructure stuff), and more flexible (by changing a single typedef, users could change their code from using LinkedList to some other list-like class and the bulk of their code would compile cleanly and hopefully with improved performance characteristics). #include // Poor man's exception handling class LinkedListIterator; class LinkedList; class Node { // No public members; this is a "private class" friend class LinkedListIterator; // A friend class friend class LinkedList; Node* next_; int elem_; }; class LinkedListIterator { public: bool operator== (LinkedListIterator i) const; bool operator!= (LinkedListIterator i) const; void operator++ (); // Go to the next element int& operator* (); // Access the current element private: LinkedListIterator(Node* p); Node* p_; friend class LinkedList; // so LinkedList can construct a LinkedListIterator }; class LinkedList { public: void append(int elem); // Adds elem after the end void prepend(int elem); // Adds elem before the beginning ... LinkedListIterator begin(); LinkedListIterator end(); ... private: Node* first_; }; Here are the methods that are obviously inlinable (probably in the same header file): inline bool LinkedListIterator::operator== (LinkedListIterator i) const { return p_ == i.p_; } inline bool LinkedListIterator::operator!= (LinkedListIterator i) const { return p_ != i.p_; } inline void LinkedListIterator::operator++() { assert(p_ != NULL); // or if (p_==NULL) throw ... p_ = p_->next_;
}

inline int& LinkedListIterator::operator*()
{
assert(p_ != NULL); // or if (p_==NULL) throw ...
return p_->elem_;
}

inline LinkedListIterator::LinkedListIterator(Node* p)
: p_(p)
{ }

inline LinkedListIterator LinkedList::begin()
{
return first_;
}

inline LinkedListIterator LinkedList::end()
{
return NULL;
}
Conclusion: The linked list had two different kinds of data. The values of the elements stored in
the linked list are the responsibility of the user of the linked list (and only the user; the linked list
itself makes no attempt to prohibit users from changing the third element to 5), and the linked
list's infrastructure data (next pointers, etc.), whose values are the responsibility of the linked list
(and only the linked list; e.g., the linked list does not let users change (or even look at!) the
various next pointers).

Thus the only get()/set() methods were to get and set the elements of the linked list, but not the
infrastructure of the linked list. Since the linked list hides the infrastructure pointers/etc., it is

able to make very strong promises regarding that infrastructure (e.g., if it were a doubly linked
list, it might guarantee that every forward pointer was matched by a backwards pointer from the
next Node).

So, we see here an example of where the values of some of a class's data is the responsibility of
users (in which case the class needs to have get()/set() methods for that data) but the data that the
class wants to control does not necessarily have get()/set() methods.

Note: the purpose of this example is not to show you how to write a linked-list class. In fact you
should not "roll your own" linked-list class since you should use one of the "container classes"
provided with your compiler. Ideally you'll use one of the standard container classes such as the
std::list template.

No comments:

Post a Comment