Skip to main content

C++ Questions I


Q1. What is the output of printf ( “%d” ) ?

Ans.
%d helps to read integer data type of a given variable.
When we write ( “%d”, x ) compiler will print the value of x assumed in the main but nothing after ( “%d” ) so the output will be a garbage value.


Q2. Explain the need for a virtual destructor.

Ans.
Destructor for the base parts are invoked automatically.
We might delete a ptr to the base type that actually points to a derived object,  if we delete a ptr to base then the base class destructor is executed and the members of the base class are cleared up. If the object is a derived type then the behavior is undefined. To ensure that the proper destructor is invoked the destructor must be virtual in the base class.


Q3. What is Mutable keyword ?

Ans.
Mutable keyword is the key to make exceptions to const objects.
Mutable data member is allowed to change during a const member function.
Mutable data member is never a const even when it is a member of a const object.
A const member function may change a mutable member.


Q4. Why is the size of an empty class not zero?

Ans.
To ensure that the addresses of two different objects will be different. For the same reason, “new” always returns pointers to distinct objects. Consider:
class Empty { };
void f()
{
Empty a, b;
if (&a == &b) cout << “impossible: report error to compiler supplier”;
Empty* p1 = new Empty;
Empty* p2 = new Empty;
if (p1 == p2) cout << “impossible: report error to compiler supplier”;
}
There is an interesting rule that says that an empty base class need not be represented by a separate byte:
struct X : Empty {
int a;
// …
};
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << “nice: good optimizer”;
}
This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this “empty base class optimization”.


Q5. Why are member functions not virtual by default?

Ans.
Because many classes are not designed to be used as base classes. Also, objects of a class with a virtual function require space needed by the virtual function call mechanism – typically one word per object. This overhead can be significant, and can get in the way of layout compatibility with data from other languages (e.g. C and Fortran).



Q6. Why are destructors not virtual by default?

Ans.
Because many classes are not designed to be used as base classes. Virtual functions make sense only in classes meant to act as interfaces to objects of derived classes (typically allocated on a heap and accessed through pointers or references).
So when should I declare a destructor virtual? Whenever the class has at least one virtual function. Having virtual functions indicate that a class is meant to act as an interface to derived classes, and when it is, an object of a derived class may be destroyed through a pointer to the base. For example:
class Base {
// …
virtual ~Base();
};
class Derived : public Base {
// …
~Derived();
};
void f()
{
Base* p = new Derived;
delete p; // virtual destructor used to ensure that ~Derived is called
}
Had Base’s destructor not been virtual, Derived’s destructor would not have been called – with likely bad effects, such as resources owned by Derived not being freed.


Q7. Why don’t we have virtual constructors?

Ans.
A virtual call is a mechanism to get work done given partial information. In particular, “virtual” allows us to call a function knowing only an interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a “call to a constructor” cannot be virtual.
Techniques for using an indirection when you ask to create an object are often referred to as “Virtual constructors”.
For example, here is a technique for generating an object of an appropriate type using an abstract class:
struct F { // interface to object creation functions
virtual A* make_an_A() const = 0;
virtual B* make_a_B() const = 0;
};
void user(const F& fac)
{
A* p = fac.make_an_A(); // make an A of the appropriate type
B* q = fac.make_a_B(); // make a B of the appropriate type
// …
}
struct FX : F {
A* make_an_A() const { return new AX(); } // AX is derived from A
B* make_a_B() const { return new BX(); } // BX is derived from B
};
struct FY : F {
A* make_an_A() const { return new AY(); } // AY is derived from A
B* make_a_B() const { return new BY(); } // BY is derived from B
};
int main()
{
FX x;
FY y;
user(x); // this user makes AXs and BXs
user(y); // this user makes AYs and BYs
user(FX()); // this user makes AXs and BXs
user(FY()); // this user makes AYs and BYs
// …
}
This is a variant of what is often called “the factory pattern”. The point is that user() is completely isolated from knowledge of classes such as AX and AY.


Q8. Can I call a virtual function from a constructor?

Ans.
Yes, but be careful. It may not do what you expect. In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn’t yet happened. Objects are constructed from the base up, “base before derived”.
Consider:
#include<string>
#include<iostream>
using namespace std;
class B {
public:
B(const string& ss) { cout << “B constructor\n”; f(ss); }
virtual void f(const string&) { cout << “B::f\n”;}
};
class D : public B {
public:
D(const string & ss) :B(ss) { cout << “D constructor\n”;}
void f(const string& ss) { cout << “D::f\n”; s = ss; }
private:
string s;
};
int main()
{
D d(“Hello”);
}
the program compiles and produce
B constructor
B::f
D constructor
Note not D::f. Consider what would happen if the rule were different so that D::f() was called from B::B(): Because the constructor D::D() hadn’t yet been run, D::f() would try to assign its argument to an uninitialized string s. The result would most likely be an immediate crash.
Destruction is done “derived class before base class”, so virtual functions behave as in constructors: Only the local definitions are used – and no calls are made to overriding functions to avoid touching the (now destroyed) derived class part of the object.
It has been suggested that this rule is an implementation artifact. It is not so. In fact, it would be noticeably easier to implement the unsafe rule of calling virtual functions from constructors exactly as from other functions. However, that would imply that no virtual function could be written to rely on invariants established by base classes. That would be a terrible mess.


Q9. Is there a “placement delete”?

Ans.
No, but if you need one you can write your own.
Consider placement new used to place objects in a set of arenas
class Arena {
public:
void* allocate(size_t);
void deallocate(void*);
// …
};
void* operator new(size_t sz, Arena& a)
{
return a.allocate(sz);
}
Arena a1(some arguments);
Arena a2(some arguments);
Given that, we can write
X* p1 = new(a1) X;
Y* p2 = new(a1) Y;
Z* p3 = new(a2) Z;
// …
But how can we later delete those objects correctly? The reason that there is no built-in “placement delete” to match placement new is that there is no general way of assuring that it would be used correctly. Nothing in the C++ type system allows us to deduce that p1 points to an object allocated in Arena a1. A pointer to any X allocated anywhere can be assigned to p1.
However, sometimes the programmer does know, and there is a way:
template<class T> void destroy(T* p, Arena& a)
{
if (p) {
p->~T(); // explicit destructor call
a.deallocate(p);
}
}
Now, we can write:
destroy(p1,a1);
destroy(p2,a2);
destroy(p3,a3);
If an Arena keeps track of what objects it holds, you can even write destroy() to defend itself against mistakes.
It is also possible to define a matching operator new() and operator delete() pairs for a class hierarchy.


Q10. Does “friend” violate encapsulation?

Ans.
No. It does not. “Friend” is an explicit mechanism for granting access, just like membership. You cannot (in a  standard conforming program) grant yourself access to a class without modifying its source. For example:
class X {
int i;
public:
void m(); // grant X::m() access
friend void f(X&); // grant f(X&) access
// …
};
void X::m() { i++; /* X::m() can access X::i */ }
void f(X& x) { x.i++; /* f(X&) can access X::i */ }


Comments

Popular posts from this blog

JUnit – Run unit test in an Sequence / Order

In JUnit, we can use @FixMethodOrder(MethodSorters.xxx) to run the test methods in a sequence or order.

import org.junit.FixMethodOrder;import org.junit.Test;import org.junit.runners.MethodSorters;importstatic org.hamcrest.CoreMatchers.is;importstatic org.junit.Assert.assertThat;//Sorts by method name@FixMethodOrder(MethodSorters.NAME_ASCENDING)publicclassExecutionOrderTest{@TestpublicvoidtestB(){assertThat(1+1,is(2));}@Testpublicvoidtest1(){assertThat(1+1,is(2));}@TestpublicvoidtestA

Create Runnable Jar - Eclipse Options

When exporting to a Runnable Jar, there are three options in eclipse Helios. Extract required libraries into JARPackage required libraries into JARCopy required libraries into sub folder next to JAR. What are differences : Extract required libraries into JAR - Extracts the actual .class files from the libraries your app uses and puts those .class files inside the runnable JAR. So, the runnable JAR will not only contain the .class files of your application, but also the .class files of all the libraries your application uses. Package required libraries into JAR - Puts the actual JAR files of the libraries into your runnable JAR. Normally, a JAR file within a JAR file cannot be loaded by the JVM. But Eclipse adds special classes to the runnable JAR to make this possible. Copy required libraries into sub folder next to JAR - Keeps the library JARs completely separate from the runnable JAR, so the runnable JAR will only contain the .class files of your application. Option #2 is convenient be…