Example #1
void Print(const Base &Item, int n)
    cout<<"ISBN:" << Item.book() //call Base::book
        <<"\tnumber sold:" << n
        <<"\t total price:" << Item.NetPrice(n) //virtual call, is resovled at run time
Example #2
int main()
    //1. virtual and  protected member
    // 1) derived class only can visit protected member in base class through derived object,
    // derived class cannot vist protected member in base class through base object
    // like Derived class
    // 2) if there is no redefination virtual function in derived class, then it will use the version in base class
    // 3) once a function is declared as virtual in a base class it remains virtual,
    //    nothing the derived classes do can change the fact that the function is virtual

    //2. dynamic binding
    // 1)two conditions i) only member functions that are specified as virtual can be dynamically bound
    //                  ii) the call must be made through a reference or a pointer to a base-class type.
    //                  Virtuals are resolved at run time only if the call is made through a reference or pointer

    // 2) i) If the function called is nonvirtual, then regardless of the actual object type,
    //       the fuction that is executed is the one defined by the base type;
    //    ii) If the function is virtual,
    //       then  then the decision as to whhich function to run is delayed until run time
    //       E.X. function with an Base reference parameter
    //        void Print(const Base &item, int n);
    Base item("world");
    //even if Derived defined its own version of the book function,
    //this call would call the one from Base;
    // the call of book function is resolved at compile time to Base::book
    Print(item, 10);// call Base::book and Base::NetPrice

    Derived bulk;
    Print(bulk, 10); //call Base::book and Derived::NetPrice, this virtual call is made through a reference
    //    iii)overriding the virtual mechanism,
    //        when a derived-class virtual calls the version from the base.
    //        Only code inside member functions should ever need to use the scope operator(like Base)
    //        to override the virtual mechanism
    Base *BaseP = &bulk;
    //   the code forces the call to NetPrice to be resolved to the version defined in Base
    //   The call will  be resolved at compile time
    double d0 = BaseP->NetPrice(23);  //thic virtual call is made through a pointer
    cout<<d0<<endl; //11.5
    double d = BaseP->Base::NetPrice(42);
    cout<<d<<endl; // 42
    //Derived *p;
    //BaseP->book(); // ok, this is a Base pointer
    BaseP->book(); //Base, actually
    //3. public, private, and protected inheritance
    //   1)in protected inheritance, the public and protected members of the base class
    // are protected members in the derived class;
    //    In private, all are private;
    // The above controls the access that users (object and members) of the derived class have
    //   Notice i) the difference between object access (public) and members access (public and protected)
    //          ii) object access only see the status in its class
    //              (private inheritance, all members in Base become private in Derived)

    //   2)Frienship is not inherited
    //   For static member, if the member is accessible(not private), we can access
    //   the static member either through the base or derived class

    //4. derived to base Conversions
    //   1) converting a derived object to a base-type reference
    //       When we pass an object of derived type (like bulk) to a function (like print),
    //   expecting a referene to base, the reference (Base &item) is bound directly to that object (bulk),
    //   The is actually a reference to bulk object, the object itself is not copied and the conversion
    //   doesn't change the derived-type object in any way. It remains a derived-type object
    Derived bulk4;
    Print(bulk4, 10); // Print(const Base&, int)
    //   2) using a derived object to initialize or assign to a base-type object
    //      In this case, we are actually calling a function: a constructor or an asignmetn operator
    // use constructor Base::Base(const Base&)
    Base item4(bulk4); // bulk4 is sliced down to its Base portion
    // use assignment operation Base::operator = (const Base&)
    // item4 = bulk4;
    //   3) no automatic conversion from the base class to a derived class

    //5. derived constructors and copy control
    //   Each derived constructor initializes its base class + its own data members
    //   Only an immediate base class can be initialized
    Derived bulk5("0-201-82", 5, 5, 0.2);
    //6. copy constructors
    //   Classes that contain only data members of class type or built-in types other than pointers
    //   usually can use the synthesized operations;
    //   Classes with pointer members often need to define their own copy control to manage these members
    Base item7;
    Derived bulk7;
    Base *bp1 = &item7;
    Base *bp2 = &bulk7;
    //process:  1)the pointers are Base, so compiler look in Base to see if bp1,bp2 are defined
    //          2)then look for the function (like NetPrice),
    //          3) if the function is virtual and the call is through a reference or pointer,
    //             then compiler generates code to determine which version to run
    //             based on the dynamic type of the object;
    //             Otherwise, compiler g enerates code to
     bp1->NetPrice(10); //virtual call Base::NetPrice run time
    bp2->NetPrice(10); //virtual call Derived::NetPrice run time
    //8) pure virtual functions
    // we want user couldn't create such objects at all