C++ Interview Questions and Answers
February 19th, 2008 by admin
Below is a comprehensive list of C++ Questions asked in interviews. Included along with the C++ questions are their answers.
Q. What’s pass by value and pass by reference in C++.
Passing by Values is passing the copy of the variable in question as the parameter to the called function. This way the actual variable remains unchanged.
Other way of pass by Value is to pass the pointer of the variable as the parameter of the called function. In this method the values of the argument changed in the called function is available in the calling function.
Pass by Reference is in the same lines as pass a pointer with some differences. In pass by reference the passed parameter is an alias of the variable in question. The called function does not need the pointer notation to work on the parameter passed and can use it as normal variable in the function. The modification of the variable in question is changed in the calling function too.
The mechanism for passing arguments is similar in both cases, it’s just the “thing” passed that is different. A pass by value results in the called function getting a local copy of the argument. When the function terminates the local copy no longer exists. A pass by reference results in the called function getting a copy of an address, usually the address of the actual argument.
Q. What is name mangling in C++? Explain in detail.
All non-static functions hare represented in the binary file as symbols. These Symbols are special text strings that uniquely identify the functions in the program, library or object file.
In C, the symbol name is same as the function name, because no two static functions can have the same name.
Where as in C++, we have more than one non-static function having the same name to support overloading of functions. Thus its not possible to use the function name as the symbol name in C++.
C++ also have many other features like classes, member functions, exception specifications that are not supported by C.
To solve this problem C++ uses name mangling. This transforms the function name and all the necessary information (like number and size of the arguments) into a weird-looking string that only the compiler knows about.
Name mangling is not standardized and thus different compilers mangle names in a different way. Some compilers change the name-mangling algorithm during b/w different versions. Even if you worked out how your particular compiler mangles names (and would thus be able to load functions via dlsym), this would most probably work with your compiler only, and might already be broken with the next version.
Q. What are copy constructors? What are different uses of copy constructors?
C++ calls a copy constructor to make the copy. If there is no copy constructor defined for the class, C++ uses the default copy constructor that copies each bit-field i.e. a shallow copy.
Special Purpose Constructor that makes a duplicated copy of an object of the same type.
Used in the following circumstances:
When defining an object initialized as a copy of an existing object.
When passing an object using call by value.
When returning an object of this type from a function.
It is not used for Assignment.
Q. What are inline functions? What is the advantage of making a function inline?
Instead of calling the function every time it is invoked, the compiler will replace the function call with a copy of the function body. If it’s a small function that gets called a lot, this can sometimes speed things up.
When the compiler inline-expands the function call, the functions code gets inserted into the callers code stream, conceptually similar to what happens with the “#define macro”. This can improve performance (depending on many other things) because the optimizer can procedurally integrate the called code - optimize the called code into the caller.
Since the compiler will copy the entire function body every time the function is called, if it is a large function (more than three or four lines), in lining can increase the size of your executable program significantly. You may want to try to see what kind of speed gains you can achieve by inlining, and also compare the increase in the size of your executable. And, just as it is sometimes easier to read functions if they are inline, it is sometimes harder to read inline functions. If a function is more than one or two lines, in-inlining it will more than likely distract a
reader who is trying to understand how the class works. In these cases, it’s probably better not to inline.
Q. Why do we need Abstract Base Classes in C++?
Often in a design, you want the base class to present only an interface for its derived classes.
That is, you don’t want anyone to actually create an object of the base class, only to upcast to it so that its interface can be used. This is accomplished by making that class abstract, which happens if you give it at least one pure virtual function. You can recognize a pure virtual function because it uses the virtual keyword and is followed by = 0. If anyone tries to make an object of an abstract class, the compiler prevents them. This is a tool that allows you to enforce a particular design.
When an abstract class is inherited, all pure virtual functions must be implemented, or the inherited class becomes abstract as well. Creating a pure virtual function allows you to put a member function in an interface without being forced to provide a possibly meaningless body of code for that member function. At the same time, a pure virtual function forces inherited classes to provide a definition for it.
When you inherit from an existing type, you create a new type. This new type contains not only all the members of the existing type (although the private ones are hidden away and inaccessible),
but more importantly it duplicates the interface of the base class. That is, all the messages you can send to objects of the base class you can also send to objects of the derived class. Since we know the type of a class by the messages we can send to it, this means that the derived class is the same type as the base class. In the previous example, “a circle is a shape.” This type equivalence via inheritance is one of the fundamental gateways in understanding the meaning of object-oriented programming.
Since both the base class and derived class have the same interface, there must be some implementation to go along with that interface. That is, there must be some code to execute when an object receives a particular message. If you simply inherit a class and don’t do anything else, the methods from the base-class interface come right along into the derived class. That means objects of the derived class have not only the same type, they also have the same behavior,
which isn’t particularly interesting.
Although inheritance may sometimes imply that you are going to add new functions to the interface, that’s not necessarily true. The second and more important way to differentiate your new class is to change the behavior of an existing base-class function. This is referred to as overriding that function.
To override a function, you simply create a new definition for the function in the derived class. You’re saying, “I’m using the same interface function here, but I want it to do something different for my new type.”
Q. Why do we need C++ classes when we can use C structures, as you can define functions and data elements for structures?
Q. What is this pointer?
Non-static member functions have a hidden parameter that corresponds to the this pointer. The this pointer points to the instance data for the object.
The interrupt hardware/firmware in the system is not capable of providing the this pointer argument.
You must use “normal” functions (non class members) or static member functions as interrupt service routines. One possible solution is to use a static member as the interrupt service routine and have that function look somewhere to find the instance/member pair that should be called on interrupt. Thus the effect is that a member function is invoked on an interrupt, but for technical reasons you need to call an intermediate function first.
Q. What is a Virtual Destructor in C++? Give detail analysis.
Normally, the action of the destructor is quite adequate. But what happens if you want to manipulate an object through a pointer to its base class (that is, manipulate the object through its generic interface)? This activity is a major objective in object-oriented programming. The problem occurs when you want to delete a pointer of this type for an object that has been created on the heap with new. If the pointer is to the base class, the compiler can only know to call the base-class version of the destructor during delete. Sound familiar? This is the same problem that virtual functions were created to solve for the general case.
Forgetting to make a destructor virtual is an insidious bug because it often doesn’t directly affect the behavior of your program, but it can quietly introduce a memory leak. Also, the fact that some destruction is occurring can further mask the problem.
Even though the destructor, like the constructor, is an “exceptional” function, it is possible for the destructor to be virtual because the object already knows what type it is (whereas it doesn’t
during construction). Once an object has been constructed, its VPTR is initialized, so virtual function calls can take place.
Q. What are pure virtual destructor?
While pure virtual destructors are legal in Standard C++, there is an added constraint when using them: you must provide a function body for the pure virtual destructor. If you could leave off the definition for a pure virtual destructor, what function body would be called during destruction? Thus, it’s absolutely necessary that the compiler and linker enforce the existence of a function body for a pure virtual destructor.
The only difference you’ll see between the pure and non-pure virtual destructor is that the pure virtual destructor does cause the base class to be abstract, so you cannot create an object of the base class (although this would also be true if any other member function of the base class were pure virtual).
The only distinction occurs when you have a class that only has a single pure virtual function: the destructor. In this case, the only effect of the purity of the destructor is to prevent the instantiation of the base class. If there were any other pure virtual functions, they would prevent the instantiation of the base class, but if there are no others, then the pure virtual destructor will do it. So, while the addition of a virtual destructor is essential, whether it’s pure or not isn’t so important.
Q. What are the methods to handle constructor failure?
Q. What is RTTI? Give details description with some practical examples?
RTTI allows you to discover type information that has been lost by upcasting.
Run-time type identification (RTTI) lets you find the exact type of an object when you only have a pointer or reference to the base type. Normally, you’ll want to intentionally ignore the exact type of an object and let the virtual function mechanism implement the correct behavior for that type. But occasionally it is very helpful to know the exact type of an object for which you only have a base pointer; often this information allows you to perform a special-case operation more efficiently.
If you have a special programming problem that’s easiest to solve if you know the exact type of a generic pointer.
When exception handling was added to C++, the implementation required that some run-time
type information be put into the virtual function tables.
RTTI, like exceptions, depends on type information residing in the virtual function table. If
you try to use RTTI on a class that has no virtual functions, you’ll get unexpected results.
dynamic_cast is one form of RTTI.
typeid keyword is used to detect the types of the pointers.
These can be compared to each other with the operator== and operator!=, and you
can also ask for the name( ) of the type, which returns a string representation of the type
name.
Note that if you hand typeid( ) a Shape*, it will say that the type is Shape*, so if you
want to know the exact type it is pointing to, you must dereference the pointer.
For example, if s is a Shape*,
cout << typeid(*s).name() << endl;
The second syntax for RTTI is called a “type-safe downcast.”
However, you know a Circle* is also a Shape*,and the compiler freely allows an upcast assignment, but you don’t know that a Shape* is necessarily a Circle*, so the compiler doesn’t allow you to perform a downcast assignment without using an explicit cast. You can of course force your way through using ordinary C-style casts or a C++ static_cast (described at the end of this chapter), which says, “I hope this is actually a Circle*, and I’m going to pretend it is.” Without some explicit knowledge that it is in fact a Circle, this is a totally dangerous thing to do. A common approach in vendor-defined RTTI is to create some function that attempts to assign (for this example) a Shape* to a Circle*, checking the type in the process. If this function returns the address, it was successful; if it returns null, you didn’t have a Circle*.
Shape* sp = new Circle;
Circle* cp = dynamic_cast<Circle*>(sp);
if(cp) cout << “cast successful”;
Q. What is setjmp and longjmp command?
These are Standard C library functions.
With setjmp( ) you save a known good state in the program, and if you get into trouble, longjmp( ) will restore that state.
The C techniques of signals and setjmp/longjmp do not call destructors, so objects aren’t properly cleaned up. This makes it virtually impossible to effectively recover from an exceptional condition because you’ll always leave objects behind that haven’t been cleaned up and that can no longer be accessed.
//: C07:Nonlocal.cpp
// setjmp() & longjmp()
#include <iostream>
#include <csetjmp>
using namespace std;
class Rainbow {
public:
Rainbow() { cout << “Rainbow()” << endl; }
~Rainbow() { cout << “~Rainbow()” << endl; }
};
jmp_buf kansas;
void oz() {
Rainbow rb;
for(int i = 0; i < 3; i++)
cout << “there’s no place like home\n”;
longjmp(kansas, 47);
}
int main() {
if(setjmp(kansas) == 0) {
cout << “tornado, witch, munchkins…\n”;
oz();
} else {
cout << “Auntie Em! “
<< “I had the strangest dream…”
<< endl;
}
} ///:~
setjmp( ) is an odd function because if you call it directly, it stores all the relevant information about the current processor state in the jmp_buf and returns zero. In that case it has the behavior of an ordinary function.
However, if you call longjmp( ) using the same jmp_buf, it’s as if you’re returning from setjmp( ) again – you pop right out the back end of the setjmp( ). This time, the value returned is the second argument to longjmp( ), so you can detect that you’re actually coming back from a longjmp( ). You can imagine that with many different jmp_bufs, you could pop around to many different places in the program. The difference between a local goto (with a label) and this nonlocal goto is that you can go anywhere with setjmp/longjmp.
The problem with C++ is that longjmp( ) doesn’t respect objects; in particular it doesn’t call
destructors when it jumps out of a scope. Destructor calls are essential, so this approach
won’t work with C++.
Q. What are aggregate classes?
Q. Write a post and prefix ++ operation in C++.
Q. Describe what happens when we have a private constructor.
Q. What are namespaces? Give details idea of different scenarios of namespaces.
Q. Which is advantageous enum or #define?
Advantages of enum are:
a) The code becomes more readable (use clear names!).
b) it is convenient way to associate constant values with names with advantage of values being generated for you.
c) enum variables offer the chance of checking the what you store in the enum so are better than #define.
d) Debuggers may be able to print values of enumeration variables in their symbolic form. While debugging (gdb) you will also see the names of the enums.
e) You can’t make typos without the compiler complaining.
f) An advantage of enum over #define is that it has scope. This means that the variable (just like any other) is only visible within the block it was declared within.
g) It is easy to extend without getting confused or forgetting to update parts of your code.
h) You are told when you forget a value in a switch.
Q. What are singleton classes? Code a sample singleton class?
The key to creating a singleton is to prevent the client programmer from having any way to create an object except the ways you provide. To do this, you must declare all constructors as private, and you must create at least one constructor to prevent the compiler from synthesizing a default constructor for you.
Q. How would you implement OO concept like encapsulation, data hiding, and inheritance using structures
Q. How can you allocate memory to an object using malloc not using a new? Can you use overloaded new? Can you actually do this?
Q. What is const keyword used in C++? What are constant functions?
Q. What is difference between, a “class depends upon” and a “class has association with” another class?
Q. In what context is mutable keyword used in C++?
This entry was posted on Tuesday, February 19th, 2008 at 11:17 am and is filed under Interview Questions. You can follow any responses to this entry through the RSS 2.0 feed. Responses are currently closed, but you can trackback from your own site.