本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录前一修订版后一修订版 | 前一修订版 | ||
cs:programming:cpp:cpp_primer:answers:chpt_15 [2024/01/14 13:46] – 移除 - 外部编辑 (未知日期) 127.0.0.1 | cs:programming:cpp:cpp_primer:answers:chpt_15 [2024/01/14 13:47] (当前版本) – ↷ 链接因页面移动而自动修正 codinghare | ||
---|---|---|---|
行 1: | 行 1: | ||
+ | ======Chapter.15====== | ||
+ | Answers for chapter 15 | ||
+ | ---- | ||
+ | * // | ||
+ | ====Ex.15.1-15.10==== | ||
+ | ==ex.15.1== | ||
+ | > | ||
+ | Virtual members are those members who expect their derived classes to override. | ||
+ | ==ex.15.2== | ||
+ | > | ||
+ | * **Private members** are accessible from their class members, but not from their derived class members. | ||
+ | * **Protected members** are accessible from both the base class members and the derived class members. | ||
+ | ==ex.15.3== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.4== | ||
+ | > | ||
+ | <code cpp> | ||
+ | class Base { ... }; | ||
+ | |||
+ | //error, a class cannot be derived from itself | ||
+ | (a) class Derived : public Derived { ... }; | ||
+ | |||
+ | //ok | ||
+ | (b) class Derived : private Base { ... }; | ||
+ | |||
+ | //error, the declaration of a derived class must not contain the derived list | ||
+ | (c) class Derived : public Base; | ||
+ | </ | ||
+ | ==ex.15.5== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.6== | ||
+ | > | ||
+ | Please check the code in exercise 15.5. | ||
+ | ==ex.15.7== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.8== | ||
+ | > | ||
+ | |||
+ | * The static type of an expression is always known at **compile time**, it is the type with which a variable is **declared** or that an **expression yields**. | ||
+ | * The dynamic type is the type of the object in memory that the variable or expression **represents**. The dynamic type may not be known //until run time//. | ||
+ | ==ex.15.9== | ||
+ | > | ||
+ | A dynamic type of an expression differs from a static type based on the type of the argument to which its corresponding parameter is bound. Assuming we have a base class '' | ||
+ | * Binding '' | ||
+ | * Binding '' | ||
+ | * Binding '' | ||
+ | ==ex.15.10== | ||
+ | > | ||
+ | |||
+ | - '' | ||
+ | - we supplied an '' | ||
+ | - Because '' | ||
+ | ==ex.15.11== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.12== | ||
+ | > | ||
+ | Yes. A final function means that subsequent classes cannot override it, although the function can still override the function it inherited. | ||
+ | ==ex.15.13== | ||
+ | > | ||
+ | <code cpp> | ||
+ | class base { | ||
+ | public: | ||
+ | | ||
+ | | ||
+ | private: | ||
+ | | ||
+ | }; | ||
+ | class derived : public base { | ||
+ | public: | ||
+ | void print(ostream &os) { print(os); os << " " << i; } //error, infinite recursive | ||
+ | private: | ||
+ | int i; | ||
+ | }; | ||
+ | </ | ||
+ | * The '' | ||
+ | * The '' | ||
+ | <code cpp> | ||
+ | void print(ostream &os) { base:: | ||
+ | </ | ||
+ | ==ex.15.14== | ||
+ | > | ||
+ | <code cpp> | ||
+ | base bobj; base *bp1 = & | ||
+ | derived dobj; base *bp2 = & | ||
+ | </ | ||
+ | <code cpp> | ||
+ | a) bobj.print(); | ||
+ | b) dobj.print(); | ||
+ | c) bp1-> | ||
+ | d) bp2-> | ||
+ | e) br1.print(); | ||
+ | f) br2.print(); | ||
+ | </ | ||
+ | ==ex.15.15== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | ==ex.15.16== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.17== | ||
+ | > | ||
+ | <code bash> | ||
+ | ex_15_16_test.cc: | ||
+ | ex_15_16_test.cc: | ||
+ | 20 | Disc_quote dq; | ||
+ | </ | ||
+ | ==ex.15.18== | ||
+ | > | ||
+ | <code cpp> | ||
+ | // d1 has type Pub_Derv, legal, public inheritance, | ||
+ | Base *p = & | ||
+ | |||
+ | // d2 has type Priv_Derv, illegal, private inheritance, | ||
+ | p = & | ||
+ | |||
+ | // d3 has type Prot_Derv, illegal, protected inheritance, | ||
+ | p = & | ||
+ | |||
+ | // dd1 has type Derived_from_Public, | ||
+ | p = & | ||
+ | |||
+ | // dd2 has type Derived_from_Private, | ||
+ | p = & | ||
+ | |||
+ | // dd3 has type Derived_from_Protected, | ||
+ | |||
+ | p = & | ||
+ | </ | ||
+ | ==ex.15.19== | ||
+ | > | ||
+ | <code cpp> | ||
+ | void memfcn(Base &b) { b = *this; } | ||
+ | </ | ||
+ | Assuming '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | ==ex.15.20== | ||
+ | Exercise 15.20: Write code to test your answers to the previous two exercises. | ||
+ | <code bash> | ||
+ | ###Test in ex.15.18 | ||
+ | #p = ∏ | ||
+ | # | ||
+ | |||
+ | #p = &prid; | ||
+ | # | ||
+ | |||
+ | #p = & | ||
+ | # | ||
+ | |||
+ | #p = & | ||
+ | # | ||
+ | |||
+ | ###Test in ex.15.19 | ||
+ | # | ||
+ | # | ||
+ | </ | ||
+ | CODE : [[https:// | ||
+ | [[https:// | ||
+ | ====Ex.15.21-15.30==== | ||
+ | ==ex.15.21== | ||
+ | > | ||
+ | |||
+ | * a) Graphical file formats (such as gif, tiff, jpeg, bmp) | ||
+ | * b) Geometric primitives (such as box, circle, sphere, cone) | ||
+ | * c) C++ language types (such as class, function, member function) | ||
+ | |||
+ | < | ||
+ | |||
+ | CODE : [[https:// | ||
+ | ==ex.15.22== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | ==ex.15.23== | ||
+ | > | ||
+ | CODE : [[https:// | ||
+ | | ||
+ | |||
+ | Please check the comments in the test file to see how the calls will be resolved.\\ \\ | ||
+ | Alternative way: using '' | ||
+ | <code cpp> | ||
+ | class D1 : public Base { | ||
+ | public: | ||
+ | using Base::fcn; | ||
+ | int fcn() override { //...// }; | ||
+ | int fcn(int); | ||
+ | virtual void f2(); // new virtual function that does not exist in Base | ||
+ | }; | ||
+ | </ | ||
+ | ==ex.15.24== | ||
+ | > | ||
+ | //A base class almost always needs a destructor, so that it can make the destructor virtual.// There may be cases in which we need to use virtual destructors when derived classes have dynamically allocated resources. | ||
+ | ==ex.15.25== | ||
+ | > | ||
+ | This how we define '' | ||
+ | <code cpp> | ||
+ | class Disc_quote : public Quote { | ||
+ | public: | ||
+ | Disc_quote() = default; | ||
+ | Disc_quote(const std:: | ||
+ | std::size_t qty, double disc): | ||
+ | | ||
+ | | ||
+ | double net_price(std:: | ||
+ | protected: | ||
+ | std::size_t quantity = 0; // purchase size for the discount to apply | ||
+ | double discount = 0.0; // fractional discount to apply | ||
+ | }; | ||
+ | </ | ||
+ | Because '' | ||
+ | ==ex.15.26== | ||
+ | > | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.27== | ||
+ | > | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | ==ex.15.28== | ||
+ | > | ||
+ | [[https:// | ||
+ | \\ \\ | ||
+ | output: | ||
+ | < | ||
+ | The total should be: 105 | ||
+ | The total after a sliced down: 150 | ||
+ | </ | ||
+ | ==ex.15.29== | ||
+ | > | ||
+ | [[https:// | ||
+ | \\ \\ | ||
+ | output: | ||
+ | < | ||
+ | The total should be: 105 | ||
+ | The total with no sliced down: 105 | ||
+ | </ | ||
+ | The smart pointer version works because the derived-to-base conversion is performed when calling the member '' | ||
+ | ==ex.15.30== | ||
+ | > | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ====Ex.15.31-15.40==== | ||
+ | ==ex.15.31== | ||
+ | > | ||
+ | <code cpp> | ||
+ | (1) Query(s1) | Query(s2) & ~ Query(s3); | ||
+ | (2) Query(s1) | (Query(s2) & ~ Query(s3)); | ||
+ | (3) (Query(s1) & (Query(s2)) | (Query(s3) & Query(s4))); | ||
+ | </ | ||
+ | |||
+ | \\ < | ||
+ | ==ex.15.32== | ||
+ | > | ||
+ | Query class manages objects with Query_base type via smart_pointer. Whenever we perform a copy control behavior over a Query-type object, we are modifying the reference counts of the smart pointer to which the object is bound. Therefore, depending on which operation is performed on the Query object, the reference counts of the smart pointer to which the object is pointed may go up, down, or even to zero and causing the Query_base object to be freed. | ||
+ | ==ex.15.33== | ||
+ | > | ||
+ | Since Query_base is an abstract class, there is no concrete object that can be constructed from it. Query_base' | ||
+ | |||
+ | ==ex.15.34== | ||
+ | > | ||
+ | <code cpp> | ||
+ | (a) List the constructors executed in processing that expression. | ||
+ | (b) List the calls to rep that are made from cout << q. | ||
+ | (c) List the calls to eval made from q.eval(). | ||
+ | </ | ||
+ | a): | ||
+ | \\ \\ < | ||
+ | |||
+ | b): | ||
+ | \\ < | ||
+ | b): | ||
+ | \\ < | ||
+ | ==ex.15.35== | ||
+ | > | ||
+ | |||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.36== | ||
+ | > | ||
+ | |||
+ | <code cpp> | ||
+ | /* output of statement a */ | ||
+ | WordQuery CSTR | ||
+ | Query CSTR | ||
+ | WordQuery CSTR | ||
+ | Query CSTR | ||
+ | WordQuery CSTR | ||
+ | Query CSTR | ||
+ | Query Copy CSTR | ||
+ | Query Copy CSTR | ||
+ | BinaryQuery CSTR | ||
+ | AndQuery CSTR | ||
+ | Query shard_ptr CSTR | ||
+ | Query Copy CSTR | ||
+ | Query Copy CSTR | ||
+ | BinaryQuery CSTR | ||
+ | OrQuery CSTR | ||
+ | Query shard_ptr CSTR | ||
+ | |||
+ | /* output of statement b */ | ||
+ | Query:: | ||
+ | BinaryQuery:: | ||
+ | Query:: | ||
+ | WordQuery:: | ||
+ | Query:: | ||
+ | BinaryQuery:: | ||
+ | Query:: | ||
+ | WordQuery:: | ||
+ | Query:: | ||
+ | WordQuery:: | ||
+ | |||
+ | </ | ||
+ | ==ex.15.37== | ||
+ | > | ||
+ | A reason for storing '' | ||
+ | |||
+ | In this program, we can see how the ''&'' | ||
+ | <code cpp> | ||
+ | /* using Query as an interface */ | ||
+ | Query(s1) & Query(s2) | Query(s3); | ||
+ | |||
+ | /* equivalent if we storing the smart pointer in each derived classes */ | ||
+ | WordQuery(s1) & WordQuery(s2) | WordQuery(s3); | ||
+ | </ | ||
+ | |||
+ | Besides, the '' | ||
+ | <code cpp> | ||
+ | operator& | ||
+ | operator|(const AndQuery & lhs, const WordQuery & rhs); // returns a smart pointer, points to an OrQuery Object | ||
+ | </ | ||
+ | ==ex.15.38== | ||
+ | >Are the following declarations legal? If not, why not? If so, explain what the declarations mean. | ||
+ | <code cpp> | ||
+ | |||
+ | // illegal. BinaryQuery is an abstract class that cannot be instanced. | ||
+ | BinaryQuery a = Query(" | ||
+ | |||
+ | /* The constructors in the following classes cannot be called by users since they are private. | ||
+ | |||
+ | // illegal. the ''&'' | ||
+ | AndQuery b = Query(" | ||
+ | |||
+ | //illegal. same reason as the above | ||
+ | OrQuery c = Query(" | ||
+ | </ | ||
+ | ==ex.15.39== | ||
+ | > | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.40== | ||
+ | > | ||
+ | '' | ||
+ | ====Ex.15.41-15.42==== | ||
+ | ==ex.15.41== | ||
+ | > Exercise 15.41: Reimplement your classes to use built-in pointers to Query_base rather than shared_ptrs. Remember that your classes will no longer be able to use the synthesized copy-control members. | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | ==ex.15.42== | ||
+ | > | ||
+ | >a) Print words only once per sentence rather than once per line. | ||
+ | >b) Introduce a history system in which the user can refer to a previous query by number, possibly adding to it or combining it with another. | ||
+ | >c) Allow the user to limit the results so that only matches in a given range of lines are displayed. | ||
+ | <color # | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | <WRAP center round box 100%> | ||
+ | Some thoughts about the other two questions: | ||
+ | * b) a new class that store the history records is not hard to implement; a vector should handle it well. The main problem is how to interpret the input string and rewrite it to commands. That may need a phaser; will come back later to do it. | ||
+ | * c) we can limited the output range of the line number to get the result. | ||
+ | </ | ||
+ |