Tuesday, February 3, 2009

C++ Interview questions



These days I am giving interviews in my field of expertise i.e. C++. Well am not expert but that is what I am looking for in terms of technology.

Ok so getting to the point, I found it useful for myself as well as other to ponder into some of the latest questions that were asked by an interviewer in India... no wonder india is the software hub.

The answers are according to my knowledge. Do comment on it and correct me wherever I am wrong.

1. What are different kinds of design patterns?

i Singleton
ii Factory
iii Proxy
iv Adapter/Wrapper
v Decorator
vi The chain of responsibility
vii Observer Pattern

2. How would you implement a Singleton Application?
Implementing the Singleton Design Pattern
By Danny Kalev

Singleton is probably the most widely used design pattern. Its intent is to ensure that a class has only one instance, and to provide a global point of access to it. There are many situations in which a singleton object is necessary: a GUI application must have a single mouse, an active modem needs one and only one telephone line, an operating system can only have one window manager, and a PC is connected to a single keyboard. I will show how to implement the singleton pattern in C++ and explain how you can optimize its design for single-threaded applications.

Design Considerations
Using a global object ensures that the instance is easily accessible but it doesn't keep you from instantiating multiple objects—you can still create a local instance of the same class in addition to the global one. The Singleton pattern provides an elegant solution to this problem by making the class itself responsible for managing its sole instance. The sole instance is an ordinary object of its class, but that class is written so that only one instance can ever be created. This way, you guarantee that no other instance can be created. Furthermore, you provide a global point of access to that instance. The Singleton class hides the operation that creates the instance behind a static member function. This member function, traditionally called Instance(), returns a pointer to the sole instance. Here's a declaration of such a class:


class Singleton
{
public:
static Singleton* Instance();
protected:
Singleton();
Singleton(const Singleton&);
Singleton& operator= (const Singleton&);
private:
static Singleton* pinstance;
};

Instead of Singleton, you can name your class Mouse, FileManager, Scheduler, etc., and declare additional members accordingly. To ensure that users can't create local instances of the class, Singleton's constructor, assignment operator, and copy constructor are declared protected. The class also declares a private static pointer to its instance, pinstance. When the static function Instance() is called for the first time, it creates the sole instance, assigns its address to pinstance, and returns that address. In every subsequent invocation, Instance() will merely return that address.

The class's implementation looks like this:


Singleton* Singleton::pinstance = 0;// initialize pointer
Singleton* Singleton::Instance ()
{
if (pinstance == 0) // is it the first call?
{
pinstance = new Singleton; // create sole instance
}
return pinstance; // address of sole instance
}
Singleton::Singleton()
{
//... perform necessary instance initializations
}

Users access the sole instance through the Instance() member function exclusively. Any attempt to create an instance not through this function will fail because the class's constructor is protected. Instance() uses lazy initialization. This means the value it returns is created when the function is accessed for the first time. Note that this design is bullet-proof—all the following Instance() calls return a pointer to the same instance:


Singleton *p1 = Singleton::Instance();
Singleton *p2 = p1->Instance();
Singleton & ref = * Singleton::Instance();

Although our example uses a single instance, with minor modifications to the function Instance(), this design pattern permits a variable number of instances. For example, you can design a class that allows up to five instances.

Optimizing Singleton for Single-Threaded Applications
Singleton allocates its sole instance on the free-store using operator new. Because operator new is thread-safe, you can use this design pattern in multi-threaded applications. However, there's a fly in the ointment: you must destroy the instance manually by calling delete before the application terminates. Otherwise, not only are you causing a memory leak, but you also bring about undefined behavior because Singleton's destructor will never get called. Single-threaded applications can easily avoid this hassle by using a local static instance instead of a dynamically allocated one. Here's a slightly different implementation of Instance() that's suitable for single-threaded applications:


Singleton* Singleton::Instance ()
{
static Singleton inst;
return &inst;
}

The local static object inst is constructed when Instance() is called for the first time and remains alive until the application terminates. Note that the pointer pinstance is now redundant and can be removed from the class's declaration. Unlike dynamically allocated objects, static objects are destroyed automatically when the application terminates, so you shouldn't destroy the instance manually.

3. What if you do not want to permit instantiation of a class?

A class type should be declared abstract only if the intent is that subclasses can be created to complete the implementation. If the intent is simply to prevent instantiation of a class, the proper way to express this is to declare a constructor (§8.8.8) of no arguments, make it private, never invoke it, and declare no other constructors. A class of this form usually contains class methods and variables. The class Math is an example of a class that cannot be instantiated; its declaration looks like this:

public final class Math {
private Math() { } // never instantiate this class
. . . declarations of class variables and methods . . .

}

Ans 2
Make it a pure virtual class. That means no implementation of any functions in the class.

4. If you do not have to use namespaces, and have two third party Libraries with the same header file name?
5. What all things would you consider while considering addition of a third party library?
6. What is a select class in socket programming?
7. What are the different Synchronization objects?

i Classic Semaphores
ii Mutex
iii Event Objects
iv Waitable timers
v Critical section Object

8. How would you handle a file that is to be accessed by three different threads?
9. What are the steps that are involved in accessing a resource with the involvement of synchronization objects?
10.What is the library you use to open and close a file?

Stream


Step 1: Creating a File Stream
An input file stream (ifstream) supports the overloaded >> operator. Likewise, an output file stream (ofstream) supports the << operator. A file stream that combines both input and output is called fstream. The following program creates an ifstream object called dictionary and prints each word in it on the screen:


#include
#include
#include
#include
using namespace std;
int main()
{
string s;
cout<<"enter dictionary file: ";
cin>>s;
ifstream dictionary (s.c_str());
if (!dictionary) // were there any errors on opening?
exit(-1);
while (dictionary >> s) cout << s <<'\n';
}

We have to call the string::c_str() member function because fstream objects accept only const char * filenames. When you pass a filename as an argument, the constructor attempts to open the specified file. Next, we use the overloaded ! operator to check the file's status. If an error has occurred, the operator will evaluate as true. The last line contains a loop that, on each iteration, reads a word from the file, copies it to s and displays it. Note that we didn't have to check for an EOF character explicitly as the overloaded >> handles this condition automatically. Furthermore, we didn't close the file explicitly because the destructor does that for us.

11. Tell me something about virtual constructors and destructors.

Constructor cannot be virtual because at the time when the constructor is invoked, the virtual table would not be available in the memory. Hence we cannot have a virtual constructor

Virtual Destructor

- A virtual destructor is one that is declared as virtual in the base class and is used to ensure that destructors are called in proper order.
- It is to be remembered that destructors are called in reverse order of inheritance
- If a base class pointer points to a derived class object and we sometime later use the delete operator to delete the object, then the derived class destructor is not called.
- But if the keyword virtual is used while the destructor is declared in base class, ,in the above case, the derived class destructor is called.

Pure Virtual Destructor

- We cannot declare a pure virtual destructor. Even if a virtual destructor is declared as pure, it will have to implement an empty body(at least) for the destructor.

2 comments:

Unknown said...

Hi There,

I am shocked, shocked, that there is such article exist!! But I really think you did a great job highlighting some of the key "C++ Interview questions"in the entire space.

I need to use 2 dimensional array in my project.

I need to bring the Output in this format

Eg i[0]j[0] i[1]j[1], i[2]j[2] using for each loop . My array size is 6 i[6] j[6] both are integers .It first go and calculate the I th value i=0 and then it come to J th for loop and calculate the J=0 . then it again go to i[1] and j[1] .. Please any one tell me the program for this kind of looping.

I am so grateful for your blog. Really looking forward to read more.

Many Thanks,
Preethi

Unknown said...

Hi Bru,


#Topic being contrived to exist for many projects simply so it can be run will be the first to hit the wall, but those projects where the functions to make existing transactions cheaper in real world applications will find the elusive real world demand.

I have
written some code
. to calculate the number of rolls of wallpaper to decorate a room.
I have compiled it and at first it worked OK, using it in my C compiler program (LCC Wedit).
Subsequently I tried running it by clicking on the executable and it does not run and returns code -1 instead of 0. Even if I return to the compiler program it comes up with the same return code.
Why is this happening?

Great effort, I wish I saw it earlier. Would have saved my day :)


Merci Beaucoup,