- Exercise 19.1
- Exercise 19.2
- Exercise 19.3
- Exercise 19.4
- Exercise 19.5
- Exercise 19.6
- Exercise 19.7
- Exercise 19.8
- Exercise 19.9
- Exercise 19.10
- Exercise 19.11
- Exercise 19.12
- Exercise 19.13
- Exercise 19.14
- Exercise 19.15
- Exercise 19.16
- Exercise 19.17
- Exercise 19.18
- Exercise 19.19
- Exercise 19.20
- Exercise 19.21
- Exercise 19.22
- Exercise 19.23
- Exercise 19.24
- Exercise 19.25
- Exercise 19.26
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.
Exer19_02.cpp | Exer19_02_StrVec.h
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); A
|\
| \
| B
| / \
|/ \
D C
(b) will fail. Because the dynamic type of pb is B, which is the base class of C. We can't use a pointer of derived class to point to a base class object.
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?
If we use a base class pointer to point to a derived class object, and derived class defines its own functions, and we want to use these functions of the object, we can use dynamic_cast to cast it to a derived class pointer or reference.
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.
Exer19_06_07_08.cpp | Exer19_06_07_08_Query.cpp | Exer19_06_07_08_Query.h | Exer19_06_07_08_TextQuery.cpp | Exer19_06_07_08_TextQuery.h
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.
Exer19_06_07_08.cpp | Exer19_06_07_08_Query.cpp | Exer19_06_07_08_Query.h | Exer19_06_07_08_TextQuery.cpp | Exer19_06_07_08_TextQuery.h
Write a typeid expression to see whether two Query_base pointers point to the same type. Now check whether that type is an AndQuery.
Exer19_06_07_08.cpp | Exer19_06_07_08_Query.cpp | Exer19_06_07_08_Query.h | Exer19_06_07_08_TextQuery.cpp | Exer19_06_07_08_TextQuery.h
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 following 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?
- The type of a pointer to member embodies both the type of a class and the type of a member of that class;
- We initialize such a pointer to point to a specific member of a class without identifying an object to which that member belongs;
- We use .* and ->* to dereference a pointer to 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.
Exer19_12.cpp | Exer19_12_Screen.h
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;The type of pmf is char(Screen::*)() const, the type of get is char() const,
so we could use pmf to point to the member function get of Screen.
What is the difference between an ordinary function pointer and a pointer to a member function?
- A pointer to a member function is declared using classname::*;
- there is no automatic conversion between a member function and a pointer to that member.
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.
Exer19_17.cpp | Exer19_17_Screen.h
Write a function that uses count_if to count how many empty strings there are in a given vector.
Exer19_18.cpp | Exer19_18_ADL.cpp
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).
Exer19_20.cpp | Exer19_20_TextQuery.cpp | Exer19_20_TextQuery.h
Write your own version of the Token class.
Exer19_21_25.cpp | Exer19_21_25_Token.cpp | Exer19_21_25_Token.h
Add a member of type Sales_data to your Token class.
Exer19_21_25.cpp | Exer19_21_25_Token.cpp | Exer19_21_25_Token.h
Add a move constructor and move assignment to Token.
Exer19_21_25.cpp | Exer19_21_25_Token.cpp | Exer19_21_25_Token.h
Explain what happens if we assign a Token object to itself.
If we assign a Token object to itself, the first condition
tok == STR && t.tok != STR is false. Then if the object holds a string, the second
condition is true. Assigning a string to it self is okay. Because a string has its
own assignment operator. If the object doesn't hold a string, else condition is true.
CopyUnion is called. In this case the object holds a built-in type object. Assigning
to itself is okay.
Write assignment operators that take values of each type in the union.
Exer19_21_25.cpp | Exer19_21_25_Token.cpp | Exer19_21_25_Token.h
Explain these declarations and indicate whether they are legal:
extern "C" int compute(int *, int);
extern "C" double compute(double *, double);The first declaration uses linkage directive to declare a function compute that's written in C and can be called by C++ programs. So does the second. The problem is C doesn't permit function overloading. So two declarations with the same name are illegal.