Some statements:
1. Result of deleting an array of derived class objects through a base class pointer is undefined.
2. Avoid default constructors, instead use ctor(s) with default value for input parameter(s).
3.
Q: C++ *_cast explanation?
A:
const : const member functions(getter function), const pointers, const variables(data member or object)
ie: const char *const m_f(…) const {}
const_cast<> operator will cast in/out between const and non-const time, but be aware of read-only memory access problem when
cast from const to non-cast, since const type variable may have been allocated in read-only memory section!
dynamic_cast, const_cast, typeid Link: http://www.cplusplus.com/doc/tutorial/tut5-4.html
dynamic_cast, is used to perform safe casts down or across an inheritance hierarchy. That is, you use dynamic_cast to cast pointers or references to base class objects into pointers or references to derived or sibling base class objects in such a way that you can determine whether the casts succeeded.1 Failed casts are indicated by a null pointer (when casting pointers) or an exception (when casting references).
i.e:
class Widget { … };
class SpecialWidget: public Widget { … };
void update(SpecialWidget *psw);
Widget *pw;
…
update(dynamic_cast<SpecialWidget*>(pw));
// fine, passes to update a pointer
// to the SpecialWidget pw points to
// if pw really points to one,
// otherwise passes the null pointer
explicit keyword: http://www.glenmccl.com/tip_023.htm
i.e.:
class A {
public:
explicit A(int);
};
void f(A) {}
void g()
{
A a1 = A(37);
A a2 = A(47);
A a3(57);
a1 = A(67);
f(A(77)); //
}
Q: What is the difference between a copy constructor and an overloaded assignment operator?
A: A copy constructor constructs a new object by using the content of the argument object. An overloaded assignment operator assigns the contents of an existing object to another existing object of the same class.
Q: What is a conversion constructor?
A: A constructor that accepts one argument of a different type.
Q: What is a virtual destructor?
A: The simple answer is that a virtual destructor is one that is declared with the virtual attribute. you destroy an object through a pointer or reference to a base class,
Q: What is a mutable member?
A: One that can be modified by the class even when the object of the class or the member function doing the modification is const.
Q: What is an explicit constructor?
A: A conversion constructor declared with the explicit keyword. The compiler does not use an explicit constructor to implement an implied conversion of types. It's purpose is reserved explicitly for construction.
Q: Describe run-time type identification.
A: The ability to determine at run time the type of an object by using the typeid operator or the dynamic_cast operator.
Q: What problem does the namespace feature solve?
A: Multiple providers of libraries might use common global identifiers causing a name collision when an application tries to link with two or more such libraries. The namespace feature surrounds a library's external declarations with a unique namespace that eliminates the potential for those collisions.
Q: Implement String class that supports intuitive string concatenation?
A: Copy constructor (pass and return object(s) by value!!!) is the one to go…
//
class String {
public:
String(); //default ctor
String(const char *value); // constructor!
String(const String &src); // copy ctor
String operator+(const String &s1, const String &s2); // overloading + operator
String& operator=(const String& rhs); // Assignment ctor
~String() { //dtor
delete [] data;
}
private:
char *data;
}; //String{}
// a possible String constructor
String::String(const char *value)
{
if (value) { // if value ptr isn't null
data = new char[strlen(value) + 1];
strcpy(data,value);
}
else { // handle null value ptr3
data = new char[1];
*data = ‘\0′; // add trailing null char
}
}
// copy ctor
String::String(const String & src) {
data = new char[strlen(src.data)+1]; //mem alloc
strcpy(data, src.data);
}
// a possible String assignment operator
String& String::operator=(const String& rhs)
{
if (this == &rhs) // Check if point to same addr.
return *this; // see Item 17
delete [] data; // delete old memory
data = // allocate new memory
new char[strlen(rhs.data) + 1];
strcpy(data, rhs.data);
return *this; // see Item 15
}
const String String::operator+(const String &s1, const String &s2)
{
String temp;
delete [] temp.data;
temp.data =
new char[strlen(s1.data) + strlen(s2.data) + 1];
strcpy(temp.data, s1.data);
strcat(temp.data, s2.data);
return temp; //return by value, invoke copy ctor!!
}
// Main func
void main() {
String a(”Hello”);
String b(” world”);
String c = a + b; // c = String(”Hello world”)
}
Q: If you have to implement Boolean type, what u need to do?
A:
typedef int bool;
const bool false = 0;
const bool true = 1;
Q: define a constant char*-based string in a header file?
A:
const char * const authorName = “Ricky Y. Sun”;
Also, how to define class-specific const?
In the scope of class body (header), prepend const with “static” modifier.
static const int NUM_TURNS = 5; // constant declaration
int scores[NUM_TURNS]; // use of constant
and in implementation file:
const int GamePlayer::NUM_TURNS; // mandatory definition;
Note that static class members should never be initialized in a class's constructor
Also Note that: class static must be defined outside the class and initialization is to 0 by default.
See sample code below:
class EnemyTarget {
public:
EnemyTarget() { ++numTargets; }
EnemyTarget(const EnemyTarget&) { ++numTargets; }
~EnemyTarget() { -numTargets; }
static size_t numberOfTargets()
{ return numTargets; }
virtual bool destroy(); // returns success of
// attempt to destroy
// EnemyTarget object
private:
static size_t numTargets; // object counter
};
// class statics must be defined outside the class;
// initialization is to 0 by default
size_t EnemyTarget::numTargets;
Q: template inline function’s advantages?
A:
// Note: all parameters are passed-by-reference!
// Also note that the max() is in standard C++ library!
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }
As compared with:
inline int max(int a, int b) { return a > b ? a : b; }
Q: Some sample C++ code?
A:
// new vs. malloc()
string *sArr1 = static_cast<string*>(malloc(10 * sizeof(string)));
string *sArr2 = new string[10];
// delete vs. free()
free(sArr1);
delete [] sArr2;
Does the pointer being deleted point to a single object or to an array of objects?
The only way for delete to know is for you to tell it. If you don't use brackets in your use of delete, delete assumes a single object is pointed to. Otherwise, it assumes that an array is pointed to
i.e:
string *stringPtr1 = new string;
string *stringPtr2 = new string[100];
…
delete stringPtr1; // delete an object
delete [] stringPtr2; // delete an array of
// objects
Q: How to write placement new()/delete() operator?
A:
void * operator new(size_t size); // operator new()
void *rawMemory = operator new(sizeof(string));
//placement new.
void * operator new(size_t, void *location)
{
return location;
}
string *ps = // call operator new[] to allocate
new string[10]; // memory for 10 string objects,
// then call the default string
// ctor for each array element
Similarly, when the delete operator is used on an array, it calls a destructor for each array element and then calls operator delete[] to deallocate the memory:
delete [] ps; // call the string dtor for each
// array element, then call
// operator delete[] to
// deallocate the array's memory
Just as you can replace or overload operator delete, you can replace or overload operator delete[].
Another example:
class X {
public:
void f();
static void * operator new(size_t size, new_handler p);
static void * operator new(size_t size) {
return ::operator new(size);
}
static void operator delete(void *p, size_t size);
};
X *px1 =
new (specialErrorHandler) X; // calls X::operator
// new(size_t, new_handler)
X* px2 = new X; // calls X::operator
// new(size_t)
An alternative is to provide a default parameter value (see Item 24) for each additional parameter you add to operator new:
class X {
public:
void f();
static
void * operator new(size_t size, //default
new_handler p = 0); //value for p
};
X *px1 = new (specialErrorHandler) X; // fine
X* px2 = new X; // also fine
// invoke delete()
inline void Airplane::operator delete(void *p,
size_t size)
{ memPool.free(p, size); }
Q: Difference between initialization and assignment in constructors?
A: We prefer initialization to assignment, not only because initialization is 3x faster, but also for the cases of: const and reference members may only be initialized, never assigned.
template<class T>
class NamedPtr {
public:
NamedPtr(const string& initName, T *initPtr);
…
private:
const string& name; // must be initialized via
// initializer list
T * const ptr; // must be initialized via
// initializer list
}; // end of class NamedPtr
// full definition of the ctor.
template<class T>
NamedPtr<T>::NamedPtr(const string& initName, T *initPtr )
: name(initName), ptr(initPtr)
{}
Note: List members in an initialization list in the order in which they are declared.
There is one time, however, when it may make sense to use assignment instead of initialization for the data members in a class. That is when you have a large number of data members of built-in types, and you want them all initialized the same way in each constructor.
1. Result of deleting an array of derived class objects through a base class pointer is undefined.
2. Avoid default constructors, instead use ctor(s) with default value for input parameter(s).
3.
Q: C++ *_cast explanation?
A:
const : const member functions(getter function), const pointers, const variables(data member or object)
ie: const char *const m_f(…) const {}
const_cast<> operator will cast in/out between const and non-const time, but be aware of read-only memory access problem when
cast from const to non-cast, since const type variable may have been allocated in read-only memory section!
dynamic_cast, const_cast, typeid Link: http://www.cplusplus.com/doc/tutorial/tut5-4.html
dynamic_cast, is used to perform safe casts down or across an inheritance hierarchy. That is, you use dynamic_cast to cast pointers or references to base class objects into pointers or references to derived or sibling base class objects in such a way that you can determine whether the casts succeeded.1 Failed casts are indicated by a null pointer (when casting pointers) or an exception (when casting references).
i.e:
class Widget { … };
class SpecialWidget: public Widget { … };
void update(SpecialWidget *psw);
Widget *pw;
…
update(dynamic_cast<SpecialWidget*>(pw));
// fine, passes to update a pointer
// to the SpecialWidget pw points to
// if pw really points to one,
// otherwise passes the null pointer
explicit keyword: http://www.glenmccl.com/tip_023.htm
i.e.:
class A {
public:
explicit A(int);
};
void f(A) {}
void g()
{
A a1 = A(37);
A a2 = A(47);
A a3(57);
a1 = A(67);
f(A(77)); //
}
Q: What is the difference between a copy constructor and an overloaded assignment operator?
A: A copy constructor constructs a new object by using the content of the argument object. An overloaded assignment operator assigns the contents of an existing object to another existing object of the same class.
Q: What is a conversion constructor?
A: A constructor that accepts one argument of a different type.
Q: What is a virtual destructor?
A: The simple answer is that a virtual destructor is one that is declared with the virtual attribute. you destroy an object through a pointer or reference to a base class,
Q: What is a mutable member?
A: One that can be modified by the class even when the object of the class or the member function doing the modification is const.
Q: What is an explicit constructor?
A: A conversion constructor declared with the explicit keyword. The compiler does not use an explicit constructor to implement an implied conversion of types. It's purpose is reserved explicitly for construction.
Q: Describe run-time type identification.
A: The ability to determine at run time the type of an object by using the typeid operator or the dynamic_cast operator.
Q: What problem does the namespace feature solve?
A: Multiple providers of libraries might use common global identifiers causing a name collision when an application tries to link with two or more such libraries. The namespace feature surrounds a library's external declarations with a unique namespace that eliminates the potential for those collisions.
Q: Implement String class that supports intuitive string concatenation?
A: Copy constructor (pass and return object(s) by value!!!) is the one to go…
//
class String {
public:
String(); //default ctor
String(const char *value); // constructor!
String(const String &src); // copy ctor
String operator+(const String &s1, const String &s2); // overloading + operator
String& operator=(const String& rhs); // Assignment ctor
~String() { //dtor
delete [] data;
}
private:
char *data;
}; //String{}
// a possible String constructor
String::String(const char *value)
{
if (value) { // if value ptr isn't null
data = new char[strlen(value) + 1];
strcpy(data,value);
}
else { // handle null value ptr3
data = new char[1];
*data = ‘\0′; // add trailing null char
}
}
// copy ctor
String::String(const String & src) {
data = new char[strlen(src.data)+1]; //mem alloc
strcpy(data, src.data);
}
// a possible String assignment operator
String& String::operator=(const String& rhs)
{
if (this == &rhs) // Check if point to same addr.
return *this; // see Item 17
delete [] data; // delete old memory
data = // allocate new memory
new char[strlen(rhs.data) + 1];
strcpy(data, rhs.data);
return *this; // see Item 15
}
const String String::operator+(const String &s1, const String &s2)
{
String temp;
delete [] temp.data;
temp.data =
new char[strlen(s1.data) + strlen(s2.data) + 1];
strcpy(temp.data, s1.data);
strcat(temp.data, s2.data);
return temp; //return by value, invoke copy ctor!!
}
// Main func
void main() {
String a(”Hello”);
String b(” world”);
String c = a + b; // c = String(”Hello world”)
}
Q: If you have to implement Boolean type, what u need to do?
A:
typedef int bool;
const bool false = 0;
const bool true = 1;
Q: define a constant char*-based string in a header file?
A:
const char * const authorName = “Ricky Y. Sun”;
Also, how to define class-specific const?
In the scope of class body (header), prepend const with “static” modifier.
static const int NUM_TURNS = 5; // constant declaration
int scores[NUM_TURNS]; // use of constant
and in implementation file:
const int GamePlayer::NUM_TURNS; // mandatory definition;
Note that static class members should never be initialized in a class's constructor
Also Note that: class static must be defined outside the class and initialization is to 0 by default.
See sample code below:
class EnemyTarget {
public:
EnemyTarget() { ++numTargets; }
EnemyTarget(const EnemyTarget&) { ++numTargets; }
~EnemyTarget() { -numTargets; }
static size_t numberOfTargets()
{ return numTargets; }
virtual bool destroy(); // returns success of
// attempt to destroy
// EnemyTarget object
private:
static size_t numTargets; // object counter
};
// class statics must be defined outside the class;
// initialization is to 0 by default
size_t EnemyTarget::numTargets;
Q: template inline function’s advantages?
A:
// Note: all parameters are passed-by-reference!
// Also note that the max() is in standard C++ library!
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }
As compared with:
inline int max(int a, int b) { return a > b ? a : b; }
Q: Some sample C++ code?
A:
// new vs. malloc()
string *sArr1 = static_cast<string*>(malloc(10 * sizeof(string)));
string *sArr2 = new string[10];
// delete vs. free()
free(sArr1);
delete [] sArr2;
Does the pointer being deleted point to a single object or to an array of objects?
The only way for delete to know is for you to tell it. If you don't use brackets in your use of delete, delete assumes a single object is pointed to. Otherwise, it assumes that an array is pointed to
i.e:
string *stringPtr1 = new string;
string *stringPtr2 = new string[100];
…
delete stringPtr1; // delete an object
delete [] stringPtr2; // delete an array of
// objects
Q: How to write placement new()/delete() operator?
A:
void * operator new(size_t size); // operator new()
void *rawMemory = operator new(sizeof(string));
//placement new.
void * operator new(size_t, void *location)
{
return location;
}
string *ps = // call operator new[] to allocate
new string[10]; // memory for 10 string objects,
// then call the default string
// ctor for each array element
Similarly, when the delete operator is used on an array, it calls a destructor for each array element and then calls operator delete[] to deallocate the memory:
delete [] ps; // call the string dtor for each
// array element, then call
// operator delete[] to
// deallocate the array's memory
Just as you can replace or overload operator delete, you can replace or overload operator delete[].
Another example:
class X {
public:
void f();
static void * operator new(size_t size, new_handler p);
static void * operator new(size_t size) {
return ::operator new(size);
}
static void operator delete(void *p, size_t size);
};
X *px1 =
new (specialErrorHandler) X; // calls X::operator
// new(size_t, new_handler)
X* px2 = new X; // calls X::operator
// new(size_t)
An alternative is to provide a default parameter value (see Item 24) for each additional parameter you add to operator new:
class X {
public:
void f();
static
void * operator new(size_t size, //default
new_handler p = 0); //value for p
};
X *px1 = new (specialErrorHandler) X; // fine
X* px2 = new X; // also fine
// invoke delete()
inline void Airplane::operator delete(void *p,
size_t size)
{ memPool.free(p, size); }
Q: Difference between initialization and assignment in constructors?
A: We prefer initialization to assignment, not only because initialization is 3x faster, but also for the cases of: const and reference members may only be initialized, never assigned.
template<class T>
class NamedPtr {
public:
NamedPtr(const string& initName, T *initPtr);
…
private:
const string& name; // must be initialized via
// initializer list
T * const ptr; // must be initialized via
// initializer list
}; // end of class NamedPtr
// full definition of the ctor.
template<class T>
NamedPtr<T>::NamedPtr(const string& initName, T *initPtr )
: name(initName), ptr(initPtr)
{}
Note: List members in an initialization list in the order in which they are declared.
There is one time, however, when it may make sense to use assignment instead of initialization for the data members in a class. That is when you have a large number of data members of built-in types, and you want them all initialized the same way in each constructor.