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: Can a copy constructor accept an object of the same class as parameter, instead of reference of the object?
A: No. It is specified in the definition of the copy constructor itself. It should generate an error if a programmer specifies a copy constructor with a first argument that is an object and not a reference.
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: How can I provide input for my class Fred?
A: Use operator overloading to provide a friend right-shift operator, operator>>. This is similar to the output operator, except the parameter doesn’t have a const: “Fred&” rather than “const Fred&”.
class Fred
{
public:
friend std::istream& operator>> (std::istream& i, Fred& fred);
private:
int i_; // Just for illustration
};
std::istream& operator>> (std::istream& i, Fred& fred)
{
return i >> fred.i_;
}
int main(){
Fred f;
std::cout << “Enter a Fred object: “;
std::cin >> f;
}
Note that operator>> returns the stream. This is so the input operations can be cascaded and/or used in a while loop or if statement.
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: Should constructors use “initialization lists” or “assignment”?
A: Initialization lists. In fact, as a rule constructors should initialize all member objects in the initialization list. Every rule has exceptions. This might happen when your class has two constructors that need to initialize this object’s data members in different orders. Or it might happen when two data members are self-referential. Or when a data- member needs a reference to this object, and you want to avoid a compiler warning about using the this keyword prior to the open curly brace of the constructor.
Q: What is the down side with runtime type identification (RTTI)?
A: The run time type identification comes with a performance penalty. Both dynamic_cast and typeid require RTTI to be maintained by the run time environment. Compiler support for RTTI may be optional.
int main () { int \* a,b; a=0; b=0; if (typeid(a) != typeid(b)) { cout \<\< "a and b are of different types:\n"; cout \<\< "a is: " \<\< typeid(a).name() \<\< '\n'; cout \<\< "b is: " \<\< typeid(b).name() \<\< '\n'; } return 0; }
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 copy constructor?
A: Constructor that initializes its object member variables ( byshallow copying) with another object of the same class. If you don’t implement one in your class then thecompiler implements one for you. Dor example:
(a) Boo Obj1(10); // calling Boo constructor
(b) Boo Obj2(Obj1); // calling boo copy constructor
(c) Boo Obj2 = Obj1;// calling boo copy constructor
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: Can you think of a situation where your program would crash without reaching the breakpoint which you set at the beginning of main()?
A: C++ allows for dynamic initialization of global variables before main() is invoked. It is possible that initialization of global will invoke some function. If this function crashes the crash will occur before main() is entered.
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: Should a class declare a member function or a friend function?
A: Use a member when you can, and a friend when you have to. Sometimes friends are syntactically better (e.g., in class Fred, friend functions allow the Fred parameter to be second, while members require it to be first). Another good use of friend functions are the binary infix arithmetic operators. E.g., aComplex + aComplex should be defined as a friend rather than a member if you want to allow aFloat + aComplex as well (member functions don’t allow promotion of the left hand argument, since that would change the class of the object that is the recipient of the member function invocation). In other cases, choose a member function over a friend function.
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: Do I need to check for NULL before delete p?
A: No. The C++ language guarantees that delete p will do nothing if p is equal to NULL. Since you might get the test backwards, and since most testing methodologies force you to explicitly test every branch point, you should not put in the redundant if test.
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 are storage qualifiers in C++ ?
A: They are:
const: Indicates that memory once initialized, should not be altered by a program.
volatile: Indicates that the value in the memory location can be altered even though nothing in the program code modifies the contents. Forces compiler to generate code to read that storage every time it is used, even if no code has written to the location.
mutable: Indicates that particular member of a structure or class can be altered even if a particular structure variable, class, or class member function is constant.
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.