15.1, 15.2, 15.3, 15.5

来源:互联网 发布:程序设计与软件开发 编辑:程序博客网 时间:2024/06/14 05:45
//15.5 Access Control and Inheritance//A derived class member or friend may access the protected members of the base class only through a derived object.class Base {protected:    int prot_mem;};class Sneaky : public Base {    friend void clobber(Sneaky &);    friend void clobber(Base &);    int j;};void clobber(Sneaky &s) { s.j = s.prot_mem = 0; }void clobber(Base &b) { b.prot_mem = 0; }//error: clobber can't access the protected members in Base//That function is not a friend of Base, yet it would be allowed to change an object oftype Base; we could circumvent the protection provided by protected for any classsimply by defining a new class along the lines of Sneaky.int main() {    return 0;}//public, private, and protected Inheritance//The purpose of the derivation access specifier is to control the access that  users of the derived class—including other classes derived from the derived class—have to the members inherited from Base:class Base {public:    void pub_mem();protected:    int prot_mem;private:    char priv_mem;};struct Pub_Derv : public Base {    int f() { return prot_mem; }    char g() { return priv_mem; }};struct Priv_Derv : private Base {    //private derivation doesn't affect access in the derived class    int f1() const { return prot_mem; }};//users of derived classint main() {    Pub_Derv d1;    Priv_Derv d2;    d1.pub_mem();    //error: pub_mem is private in the derived class    d2.pub_mem();}//classes derived from the derived classclass Base {public:    void pub_mem();protected:    int prot_mem;private:    char priv_mem;};struct Pub_Derv : public Base {    int f() { return prot_mem; }    //char g() { return priv_mem; }};struct Priv_Derv : private Base {    int f1() const { return prot_mem; }};struct Derived_from_Public : public Pub_Derv {    int use_base() { return prot_mem; }};struct Derived_from_Private : public Priv_Derv {    int use_base() { return prot_mem; }};int main() {    return 0;}//Friendship and Inheritanceclass Base {    friend class Pal;public:    void pub_mem();protected:    int prot_mem;private:    char priv_mem;};class Sneaky : public Base {    friend void clobber(Sneaky &);    friend void clobber(Base &);    int j;};class Pal {public:    int f(Base b) { return b.prot_mem; }    //error: Pal is not a friend of Sneaky    //int f2(Sneaky s) { return s.j; }    //That access includes access to Baseobjects that are embedded in an object of a type derived from Base.    int f3(Sneaky s) { return s.prot_mem; }};class D2 : public Pal {public:    //error: friendship is not ingerited; each class controls access to its members    int mem(Base b) { return b.prot_mem; }};int main() {    return 0;}//exempting individual membersclass Base {public:    size_t size() const { return n; }protected:    size_t n;};class Derived : private Base {public:    using Base::size;protected:    using Base::n;};//Exercises Section 15.5Exercise 15.18:Base *p = &d1; // d1 has type Pub_Derv  legalp = &d2; // d2 has type Priv_Derv   illegalp = &d3; // d3 has type Prot_Derv   illegalp = &dd1; // dd1 has type Derived_from_Public   legalp = &dd2; // dd2 has type Derived_from_Private  illegalp = &dd3; // dd3 has type Derived_from_Protected    illegalUser code may use the derived-to-base conversion only if D inherits publicly from B.Exercise 15.19:For member functions and friends of D, if inherrits is direct, all can use the derived-to-base conversion, if indirect inherits, only private can not.Hence, below are legal.pub_derv.priv_derv.prot_derv.derived_from_public.derived_from_public.derived_from_protected.Exercise 15.20:class Base {public:    void pub_mem();protected:    int prot_mem;private:    char priv_mem;};struct Pub_Derv : public Base {    void memfcn(Base &b) { b = *this; }};struct Priv_Derv : private Base {    void memfcn(Base &b) { b = *this; }};struct Prot_Derv : protected Base {    void memfcn(Base &b) { b = *this; }};struct Derived_from_Public : public Pub_Derv {    void memfcn(Base &b) { b = *this; }};struct Derived_from_Private : public Priv_Derv {    //void memfcn(Base &b) { b = *this; }};struct Derived_from_Protected : public Prot_Derv {    void memfcn(Base &b) { b = *this; }};int main() {    Pub_Derv d1;    Base *p = &d1;    Priv_Derv d2;    //p = &d2;    Prot_Derv d3;    //p = &d3;    Derived_from_Public dd1;    p = &dd1;    Derived_from_Private dd2;    //p = &dd2;    Derived_from_Private dd3;    //p = &dd3;        return 0;}Exercise 15.21:class Shape {public:    using Coordinate = pair<double, double>;        Shape() = default;    Shape(const string &n) : name(n) { }        virtual double area() const = 0;    virtual double perimeter() const = 0;        virtual ~Shape() = default;private:    string name;};class Rectangle : public Shape {public:    Rectangle() = default;    Rectangle(const string &n, const Coordinate &a, const Coordinate &b, const Coordinate &c, const Coordinate &d) :     shape(n), a(a), b(b), c(c), d(d) { }        ~Rectangle() = default;protected:    Coordinate a, b, c, d;};class Square : public Rectangle {public:    Square() = default;    Square(const string &n, const Coordinate &a, const Coordinate &b, const Coordinate &c, const Coordinate &d) :     Rectangle(n, a, b, c, d) { }        ~Square() = default;};int main() {    return 0;}
//15.1. OOP: An Overview//15.2. Defining Base and Derived Classesclass Quote {public:    Quote() = default;    Quote(const string &book, double sales_price): bookNo(book), price(sales_price) { }        string isbn() const { return bookNo; }        virtual double net_price(size_t n) const { return n * price; }        virtual ~Quote() = default;private:    string bookNO;protected:    double price = 0.0;};class Bulk_quote : public Quote {public:    double net_price(size_t) const override;};double print_total(ostream &os, const Quote &item, size_t n) {    double ret = item.net_price(n);    os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << endl;    return ret;}int main() {    print_total(cout, basic, 20);    print_total(cout, bulk, 20);}Exercises Section 15.2.1Exercise 15.1://A virtual member in a base class expects ites derived class define its own version. In particular base classes ordinarily should define a virtual destructor, even if it does no work.Exercise 15.2://private member: base class itset and friend can access//protected members: base class itself, friend and derived classes can access//Inheritance and static Membersclass Base {public:    static void statmem() { }};class Derived : public Base {    void f(const Derived &);};void Derived::f(const Derived &derived_obj) {    Base::statmem();    Derived::statmem();    derived_obj.statmem();    statmem();}int main() { return 0; }//Declarations of Derived Classes//The derivation list, and all other details of the definition, must appear together in the class body.class Bulk_quote : public Quote;class Bulk_quote;//A class must be defined, not just declared, before we can use it ans a base classclass Quote;class Bulk_quote : public Quote { };int main() { return 0; }//A base class can itself be a derived class:class Base { };class D1 : public Base { };class D2 : public D1 { };//Preventing Inheritanceclass NoDerived final { };class Base { };class Last final : Base { };class Bad : NoDerived { };//errorclass Bad2 : Last { };//errorint main() { return 0; }Exercises Section 15.2.2//Exercise 15.4: Which of the following declarations, if any, are incorrect? Explain why.class Base { ... };(a) class Derived : public Derived { ... };//incorrect, derived itself(b) class Derived : private Base { ... };//incorrect, it is a defination not a declaration(c) class Derived : public Base;//incorrect, A derived class is declared like any other class. The declaration contains the class name but does not include its derivation list.//Exercise 15.5: Define your own version of the Bulk_quote class.//Exercise 15.6: Test your print_total function from the exercises in §15.2.1 (p. 595) by passing both Quote and Bulk_quote objects o thatfunction.//Exercise 15.7: Define a class that implements a limited discount strategy, which applies a discount to books purchased up to a given limit. If the number of copies exceeds that limit, the normal price applies to those purchased beyond the limit.class Quote {public:    Quote() = default;    Quote(const string &book, double sales_price): bookNo(book), price(sales_price) { }    string isbn() const { return bookNo; }    virtual double net_price(size_t n) const { return n * price; }    virtual ~Quote() = default;private:    string bookNo;protected:    double price = 0.0;};class Bulk_quote : public Quote {public:    Bulk_quote() = default;    Bulk_quote(const string &book, double p, size_t qty, double dis) :    Quote(book, p), min_qty(qty), discount(dis) { }    double net_price(size_t cnt) const override {        if(cnt >= min_qty) return cnt * (1 - discount) * price;        else return cnt * price;    }private:    size_t min_qty = 0;    double discount = 0.0;};double print_total(ostream &os, const Quote &item, size_t n) {    double ret = item.net_price(n);    os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << endl;    return ret;}class Limited_quote : public Bulk_quote {public:    Limited_quote() = default;    Limited_quote(const string &book, double p, size_t qty, double dis, int n): Bulk_quote(book, p, qty, dis), lim_n(n) { }    double net_price(size_t n) const override {        if(n <= lim_n) return Bulk_quote::net_price(n);        else return Bulk_quote::net_price(lim_n) + Quote::net_price(n-lim_n);    }private:    unsigned int lim_n;};int main() {    Quote basic("12-34-45678", 10);    Bulk_quote bulk("12-34-45678", 10, 10, 0.2);    Limited_quote limit("12-34-45678", 10, 10, 0.2, 10);    print_total(cout, basic, 10);    print_total(cout, bulk, 10);    print_total(cout, limit, 11);    return 0;}//There Is No Implicit Conversion from Base to Derivedclass Quote { };class Bulk_Quote : public Quote { };int main() {    Quote base;    Bulk_Quote *bulkp = &base; //error cannot convert 'Quote*' to 'Bulk_Quote'    Bulk_Quote &bulkRef = base;//error invalid inititalization of reference of type 'Bulk_Quote&' from 'Quote'    return 0;}//we cannot convert from base to derived even when a base pointer or reference is bound to a derived objectclass Quote { };class Bulk_Quote : public Quote { };int main() {    Bulk_Quote bulk;    Quote *itemP = &bulk;    Bulk_Quote *bulkP = itemP;    return 0;}//Exercises Section 15.2.3//Exercise 15.8: Define static type and dynamic type.//The static type of an expression is always known at compile time//The dynamic type is the type of the object in memory that the variable or expression represents. May be know at run-time//Exercise 15.9: When is it possible for an expression¡¯s static type to differ from its dynamic type? Give three examples in which the static and dynamictype differ.//the static type of a pointer or reference to a base classs may differ from its dynamic type //Exercise 15.10: Recalling the discussion from ¡ì8.1 (p. 311), explain howthe program on page 317 that passed an ifstream to the Sales_dataread function works.


15.3. Virtual Functions//override and final specifierstruct B {    virtual void f1(int) const;    virtual void f2();    void f3();};struct D1 : B {    void f1(int) const override;    //void f2(int) override;    //void f3() override;    //void f4() override;};struct D2 : B {    void f1(int) const final;};struct D3 : D2 {    void f2();    void f1(int) const;};Exercises Section 15.3//Exercise 15.11: Add a virtual debug function to your Quote class hierarchy//that displays the data members of the respective classes.class Quote {public:    Quote() = default;    Quote(const string &book, double sales_price): bookNo(book), price(sales_price) { }    string isbn() const { return bookNo; }    virtual void debug() const { cout << "bookNo = " << bookNo << " " << " price = " << price << " "; }    virtual double net_price(size_t n) const { return n * price; }    virtual ~Quote() = default;private:    string bookNo;protected:    double price = 0.0;};class Bulk_quote : public Quote {public:    Bulk_quote() = default;    Bulk_quote(const string &book, double p, size_t qty, double dis) :    Quote(book, p), min_qty(qty), discount(dis) { }    void debug() const override { cout << "min_qty = " << min_qty << " " << "discount = " << discount << " "; }    double net_price(size_t cnt) const override {        if(cnt >= min_qty) return cnt * (1 - discount) * price;        else return cnt * price;    }private:    size_t min_qty = 0;    double discount = 0.0;};double print_total(ostream &os, const Quote &item, size_t n) {    double ret = item.net_price(n);    os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << endl;    return ret;}void print_debug(const Quote& q) { q.debug(); }int main() {    Quote q("12-34-45678", 10);    Bulk_quote bq("22-34-45678", 20, 10, 0.2);    //no dynamic binding    Quote &r = q;    r.debug(); cout << endl;    r = bq;    r.debug(); cout << endl;    cout << "=====================\n";    //dynamic binding    print_debug(q); cout << endl;    print_debug(bq); cout << endl;    return 0;}//Exercise 15.12: Is it ever useful to declare a member function as both//override and final? Why or why not?//Sure. override mean overriding the virtual function in base class. final is just for the lower classes at the hierarchy.//Exercise 15.13: Given the following classes, explain each print function://If there is a problem in this code, how would you fix it?class base {public:    string name() { return basename; }    virtual void print(ostream &os) { os << basename; }private:    string basename = "base\n";};class derived : public base {public:    void print(ostream &os) override { base::print(os); os << "derived\n" << i; }private:    int i = 0;};int main() {    base b;    derived d;    b.print(cout);    d.print(cout);    return 0;}//Exercise 15.14: Given the classes from the previous exercise and the//following objects, determine which function is called at run time:/*base bobj; base *bp1 = &bobj; base &br1 = bobj;derived dobj; base *bp2 = &dobj; base &br2 = dobj;(a) bobj.print();(b) dobj.print();(c) bp1->name();(d) bp2->name();(e) br1.print();(f) br2.print();*/class base {public:    base(const string &s) : basename(s) { }    string name() { return basename; }    virtual void print(ostream &os) { os << basename << endl; }private:    string basename;};class derived : public base {public:    derived(const string &s, int i) : base(s), i(i) { }    void print(ostream &os) override { base::print(os); os << " " << i << endl; }private:    int i = 0;};int main() {    base bobj("bobj"); base *bp1 = &bobj; base &br1 = bobj;    derived dobj("dobj", 10); base *bp2 = &dobj; base &br2 = dobj;    //compile    bobj.print(cout);    dobj.print(cout);    //compile    cout << bp1->name() << endl;    cout << bp2->name() << endl;    //run time    br1.print(cout);    br2.print(cout);    return 0;}


原创粉丝点击