C++ Pro Flashcards
Q: Give the type for a function pointer to a member function of Foo that returns int and takes a char and float parameters.
A: int (Foo::*)(char,float)
Q: What are some ways try / catch / throw can improve software quality?
A: By eliminating one of the reasons for if statements. The commonly used alternative to try / catch / throw is to return a return code (sometimes called an error code) that the caller explicitly tests via some conditional statement such as if. For example, printf(), scanf() and malloc() work this way: the caller is supposed to test the return value to see if the function succeeded. Although the return code technique is sometimes the most appropriate error handling technique, if statements can be the source of many bugs.
throw also forces a run-time check, if only trivially, because an uncaught exception will generate a message to a user, hopefully containing information about the type of fault. A return code, on the other hand, can be ignored causing a crash with no useful message. The source of the fault must then be traced backwards from the crash point, which can be far away in the code.
Q: What is the assignment operator?
A: The default assignment operator handles assigning one object to another of the same class. Member to member copy is done via shallow copy.
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: How do you handle a constructor that fails?
A: throw an exception. Constructors don’t have a return type, so it’s not possible to use return codes. The best way to signal constructor failure is therefore to throw an exception.
Q: What are some advantages/disadvantages of using friend functions?
A: They provide a degree of freedom in the interface design options. Member functions and friend functions are equally privileged (100% vested). The major difference is that a friend function is called like f(x), while a member function is called like x.f(). Thus the ability to choose between member functions (x.f()) and friend functions (f(x)) allows a designer to select the syntax that is deemed most readable, which lowers maintenance costs.
The major disadvantage of friend functions is that they require an extra line of code when you want dynamic binding. To get the effect of a virtual friend, the friend function should call a hidden (usually protected) virtual member function. This is called the Virtual Friend Function Idiom.
Q: When you write a derived class’s destructor, do you need to explicitly call the destructor for my base class?
A: No. You never need to explicitly call a destructor (except with placement new).
A derived class’s destructor (whether or not you explicitly define one) automagically invokes the destructors for base class subobjects. Base classes are destructed after member objects.
In the event of multiple inheritance, direct base classes are destructed in the reverse order of their appearance in the inheritance list.
Order dependencies with virtual inheritance are trickier. If you are relying on order dependencies in a virtual inheritance hierarchy, you’ll need a lot more information than we have here.
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: How do I convert a number to a string?
A: The simplest way is to use a stringstream:
inline std::string stringify(double x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion(“stringify(double)”);
return o.str();
}
Q: What are the differences between a C++ struct and C++ class?
A: The default member and base class access specifiers 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 wrap a new Foo() in a smart pointer?
A:
std::auto_ptr z (new Foo());
Q: What is a const_cast?
A: It changes the constness of any pointer or reference, so converts from const to not-const, or from not-const to const.
Q: How many ways are there to initialize an int with a constant?
A: Two that I know of:
(a) int foo = 123;
(b) int bar(123);
Q: How do I allocate / unallocate an array of things?
A: Use p = new T[n] and delete[] p:
Any time you allocate an array of objects via new (usually with the [n] in the new expression), you must use [] in the delete statement. This syntax is necessary because there is no syntactic difference between a pointer to a thing and a pointer to an array of things (something we inherited from C).
Q: What is an inline function?
A: The inline keyword tells the compiler to substitute the code within the function definition for every instance of a function call. However, substitution occurs only at the compiler’s discretion.
Q: What are the benefits of operator overloading?
A: By overloading standard operators on a class, you can exploit the intuition of the users of that class. This lets users program in the language of the problem domain rather than in the language of the machine.The ultimate goal is to reduce both the learning curve and the defect rate.
Q: After p = new Fred[n], how does the compiler know there are n objects to be destructed during delete[] p?
A: Short answer: Magic. Long answer: The run-time system stores the number of objects, n, somewhere where it can be retrieved if you only know the pointer, p. There are two popular techniques that do this. Both these techniques are in use by commercial-grade compilers, both have tradeoffs, and neither is perfect. These techniques are:Over-allocate the array and put n just to the left of the first Fred object. Use an associative array with p as the key and n as the value.
Q: What operators can/cannot be overloaded?
A: Most can be overloaded. The only C operators that can’t be are . and ?: (and sizeof, which is technically an operator).
C++ adds a few of its own operators, most of which can be overloaded except :: and .*.
Here’s an example of the subscript operator (it returns a reference).
class Array {
public:
int& operator[] (unsigned i) { if (i > 99) error(); return data[i]; }
private:
int data[100];
};
int main()
{
Array a;
a[10] = 42;
a[12] += a[13];
…
}
Q: What is a Pure Virtual Function?
A: virtual foo() = 0;It is an error to define a pure virtual function in the class where it was declared or to instantiate the abstract class. Subclasses may define the function, otherwise it remains a pure virtual function in the subclass as well.
Q: How does free know the size of memory to be deleted.?int *i = (int *)malloc(12); followed by free(i); how did free function call know how much of memory to delete?
A: It depends on the implementation, but there is usually a malloc header added to all the memory allocated through malloc. On Linux it’s 4 bytes of memory preceding the memory returned to you, which contains the number of bytes allocated + 4(itself). So when you say,int *i = (int *)malloc(12); it allocates 16 bytes.
Q: What is stack unwinding?
A: It is a process during exception handling when the destructor is called for all local objects in the stack between the place where the exception was thrown and where it is caught.
Q: Can you drop the [] when deleteing array of some built-in type (char, int, etc)?
A: No! Sometimes programmers think that the [] in the delete[] p only exists so the compiler will call the appropriate destructors for all elements in the array. Because of this reasoning, they assume that an array of some built-in type such as char or int can be deleted without the []. But this is wrong, and it can cause a disaster at runtime. In particular, the code that’s called for delete p is operator delete(void*), but the code that’s called for delete[] p is operator delete. The default behavior for the latter is to call the former, but users are allowed to replace the latter with a different behavior (in which case they would normally also replace the corresponding new code in operator new). If they replaced the delete[] code so it wasn’t compatible with the delete code, and you called the wrong one (i.e., if you said delete p rather than delete[] p), you could end up with a disaster at runtime.
Q: When should you use references, and when should you use pointers?
A: Use references when you can, and pointers when you have to. References are usually preferred over pointers whenever you don’t need “reseating”. This usually means that references are most useful in a class’s public interface. References typically appear on the skin of an object, and pointers on the inside.
The exception to the above is where a function’s parameter or return value needs a “sentinel” reference, a special reference value that does not refer to an object.
Additionally, pointers are useful when you need one variable to indicate varying objects over its lifetime. Permanent relationships could be modeled with a reference, but a more dynamic relationship can use a pointer.
Q: What are some examples of operator overloading?
A: Here are a few of the many examples of operator overloading:
myString + yourString might concatenate two std::string objects
myDate++ might increment a Date object
a * b might multiply two Number objects
a[i] might access an element of an Array
objectx = *p might dereference a “smart pointer” that “points” to a disk record