Write your own operator new(size_t) function using malloc and use free to write the operator delete(void*) function.
By default, the allocator class uses operator new to obtain storage and operator delete to free it. Recompile and rerun your StrVec programs (§ 13.5, p. 526) using your versions of the functions from the previous exercise.
Given the following class hierarchy in which each class defines a public default constructor and virtual destructor:
class A { /* . . . */ };
class B : public A { /* . . . */ };
class C : public B { /* . . . */ };
class D : public B, public A { /* . . . */ };
which, if any, of the following dynamic_casts fail?
(a) A *pa = new C;
B *pb = dynamic_cast< B* >(pa);
(b) B *pb = new B;
C *pc = dynamic_cast< C* >(pb);
(c) A *pa = new D;
B *pb = dynamic_cast< B* >(pa);
Using the classes defined in the first exercise, rewrite the following code to convert the expression *pa to the type C&:
if (C *pc = dynamic_cast< C* >(pa))
// use C’s members
} else {
// use A’s members
}
When should you use a dynamic_cast instead of a virtual function?
Write an expression to dynamically cast a pointer to a Query_base to a pointer to an AndQuery (§ 15.9.1, p. 636). Test the cast by using objects of AndQuery and of another query type. Print a statement indicating whether the cast works and be sure that the output matches your expectations.
Write the same cast, but cast a Query_base object to a reference to AndQuery. Repeat the test to ensure that your cast works correctly.
Write a typeid expression to see whether two Query_base pointers point to the same type. Now check whether that type is an AndQuery.
Write a program similar to the last one in this section to print the names your compiler uses for common type names. If your compiler gives output similar to ours, write a function that will translate those strings to more human-friendly form.
Given the following class hierarchy in which each class defines a public default constructor and virtual destructor, which type name do the follow- ing statements print?
class A { /* . . . */ };
class B : public A { /* . . . */ };
class C : public B { /* . . . */ };
(a) A *pa = new C;
cout << typeid(pa).name() << endl;
(b) C cobj;
A& ra = cobj;
cout << typeid(&ra).name() << endl;
(c) B *px = new B;
A& ra = *px;
cout << typeid(ra).name() << endl;
What is the difference between an ordinary data pointer and a pointer to a data member?
Define a pointer to member that can point to the cursor member of class Screen. Fetch the value of Screen::cursor through that pointer.
Define the type that can represent a pointer to the bookNo member of the Sales_data class.
Is the following code legal? If so, what does it do? If not, why?
auto pmf = &Screen::get_cursor;
pmf = &Screen::get;
What is the difference between an ordinary function pointer and a pointer to a member function?
Write a type alias that is a synonym for a pointer that can point to the avg_price member of Sales_data.
Define a type alias for each distinct Screen member function type.
Write a function that uses count_if to count how many empty strings there are in a given vector.
Write a function that takes a vector<Sales_data> and finds the first element whose average price is greater than some given amount.
Nest your QueryResult class inside TextQuery and rerun the programs you wrote to use TextQuery in § 12.3.2 (p. 490).
Write your own version of the Token class.
Add a member of type Sales_data to your Token class.
Add a move constructor and move assignment to Token.
Explain what happens if we assign a Token object to itself.
Write assignment operators that take values of each type in the union.
Explain these declarations and indicate whether they are legal:
extern "C" int compute(int *, int);
extern "C" double compute(double *, double);