Saturday, May 31, 2008

C puzzles #2

• 13.How can you prevent a class from being inherited ?

ANSWER:
Don't provide a default public, or protected constructor, but provide a private constructor. Now you will not be able to inherit from this class. That is you can not derive a class making this a base class. You can not directly create an instance of this class too. Now you might be thinking, then what is the use of this class. Dont worry, you can create an instance of this class like the following.

class A{
public:
static A* Create(){A *a=new A; return a; }
void Print(){printf("Hello from A\n");}

private:
A(){printf("Constructor of A\n");}
};

int main(int argc, char *argv[])
{
A *a;
a = A::Create();
a->Print();
}
• 14. If you declare two classes having a member function of the same name and if you derive a third class from both the classes (multiple inheritance) will the compiler give an error ?

ANSWER:
No. If you just derive a class from both the base classes, the compiler will not give error. But if you try to access this member function through the derived class instance, the compiler gives error.
• 15. What is the memory required for storing an object of the following class.

class A{
public:
int a;
void func(){};
};

choices:
1. The memory required for storing the integer a, or
2. The sum of memory required for storing the integer value a, the memory required for storing a pointer to the function func() and the memory required for storing the 'this' pointer of the class ?

ANSWER:
(1) is the right answer. ie, the memory required for storing the integer a. In otherwords, the memory required for storing all the data members of the class.

Actually all the member functions of the class will be internally converted to global functions with a hidden parameter 'this' pointer, ie a pointer to the instance of the class. ie, func will be internally treated by the compiler as a global function func(A *a). So no extra memory is required for storing a pointer to the member function for each instance

You might have one question. what about the memory required to store the 'this pointer' of this object ?

'this pointer' is something that is passed to a member function implicitly by the compiler and hence not part of the overall size of a class variable.
• 16. Which of the statements in the main will invoke the copy constructor of class A ?

class A{
public:
int i;
A(){i=0;}
A(int j){i=j;}
A(A &a){cout << "In copy constructor"; i=a.i;}
};

int main()
{
A a(10);

A b;
b=a;

A c=a;

A d(a);

return 0;
}

ANSWER:
The copy constructor will be called for 'A c=a' and 'A d(a)'. ie, only for the assignment at the time of creating the object. Not for the assignment operations afterwards.ie, for the statement b=a, the default assignment operation will be called, not the copy constructor.
• 17. While declaring the copy constructor why do you have to use the reference of the class variable in the parameter list like the following

class{
A(A &a){ ... }
};

Why don't you just use A(A a){...} ?

ANSWER:
Consider the following statements

A a;
A b(a);

Here when you call A b(a), the copy constructor of A gets invoked. At this time if you don't use reference, 'a' will be passed to the copy constructor 'by value'. When you pass a variable by value, the copy constructor of the class should get invoked. That means, an invokation of the copy constructor will again call the copy constructor. This will result in recursion. But most of the modern compilers will detect this and give you an error message.
• 18. What is the problem with the following program ?

class A
{
public:
A(){str = new char [12]; strcpy(str, "Hello World");};
~A() {delete [] str;}
void PrintVal(){printf("%s\n", str);};
private:
char *str;
};

void DisplayString(A a)
{
a.PrintVal();
}

int main()
{
A b;
DisplayString(b);
b.PrintVal();
}

ANSWER:
When you call the function 'DisplayString', the value of b will be passed to the parameter 'a'. At this time the default copy constructor will be called which will copy all the members of 'b' into 'a', including the 'char *' variable 'str'. But note that only the pointer will be copied and no memory will be allocated for the 'str' member of 'a'. Since 'a' is a parameter for DisplayString, it will be created in the stack and when you come out of the function, 'a' gets destroyed. At that time the destructor of 'a' will be called, which will result in deleting the member 'str'. But since 'str' of both 'a' and 'b' point to the same memory location, and the memory pointed to by 'str' of 'a' is deleted, now 'str' of 'b' will point to an invalid location. And when you call b.PrintVal(), it will result in an invalid memory access and when the destructor of 'b' is called, that will try to delete the 'str' of 'b' resulting in a segmentation fault. Inorder to avoid this you should provide a copy constructor for the class A like the following

A (A &a){str = new char[strlen(a.str)+1]; strcpy(str, a.str);};

This will make sure that memory is allocated for 'str' whenever a copy constructor is invoked
• 19. This is actually a UNIX/C question. If you write a program with the following segment and execute it how many times the string "Hello World" will be printed into the file test.txt ?
FILE *fp = fopen("test.txt", "w");
fork();
fprintf(fp, "Hello World\n");

ANSWER:
The answer is simple. "Hello World" will be printed two times into the file test.txt. The reason is that fork creates a child process which is identical to this process and start executing from the statement after fork. So fprintf will be executed by both parent and child and so it will be printed twice.
• 20. OK, now look at the following one. How many times "Hello World" will be written in this case ?
FILE *fp = fopen("test.txt", "w");
fprintf(fp, "Hello World\n");
fork();

ANSWER:
If you answered "one" it is wrong ! In this case also "Hello World" will be printed twice into the file. But how ? Child starts executing only from the statement after fork call, then how "Hello World" will be printed twice ? OK, here you need to go little more into the system. The fprintf statement is a request for a buffered print. That is, the system keeps the contents into a buffer, and later when it finds that the resources are free, it prints the stuff. But mean time fork gets executed and so the buffer is duplicated for the child also ! So both the parent and child prints the string into the file. How can you overcome this problem ? Immediately after the fprintf statement, make a call to fflush(0), so that all the bufferes are flushed before proceeding to the fork system call.

No comments: