E N D
CHAPTER 10Inheritance继承 Introduction A key feature of an object-oriented language in inheritance. Inheritance is the ability to define new classes using existing classes as a basis. The new class inherits the attributes and behaviors of the classes on which it is based, and it can also have attributes and behaviors that are specific to it. 继承是面向对象语言的重要特征之一。继承是把已有类作为基类定义新的类。这个新的类继承了基类的属性和操作,而且还可以具有自己特定的属性和操作。
10.1 OBJECT-ORIENTED DESIGN USING INHERITANCE • Three relationships are commonly used in object-oriented design : • is-a relationships • Hierarchy relationship. It specifies that one abstraction is a specialization • of another. • has-a relationships • Contain relationship. Some object is part of another. • uses-a relationships • One object uses another object in some way.
B1 B2 C2 C1 is-a relationships A Base class of B1 and B2 Derived class of A Base class of C1, C2 and C3 Derived class of A Base class of C3 Derived class of B1 C3 Derived class of B1 and B2 Multiple inheritance
has-a relationships class A { … B DMi … FM } ; class B { … DM … FM } ;
uses-a relationships class A { … DM … FMj ( B & … ) } ; class B { … DM … FM } ;
10.3.1 Declaring a derived class class DerivedClass : public BaseClass { public : // public section … private : // private section … } ;
10.3.1 Declaring a derived class classDerivedClass: public BaseClass { public : // public section … private : // private section … } ; Derived class name
10.3.1 Declaring a derived class class DerivedClass : public BaseClass { public : // public section … private : // private section … } ; Access specifier (usually public)
10.3.1 Declaring a derived class class DerivedClass : public BaseClass{ public : // public section … private : // private section … } ; Class name of base class
Example Declare vehicle class and derived class car: class vehicle{ public : void initialize (int in_wheels , float in_weight ) ; int get_wheels ( ) ; float get_weight ( ) ; float get_loading ( ) ; private : int wheels ; float weight ; float loading ; }; class car: publicvehicle{ public : void initialize ( int in_wheels , float in_weight , int people = 4 ) ; int passengers ( ) ; private : int passenger_load ; };
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … }
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } Derived class name
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } Derived class constructor parameter list
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } Base class name
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } Base class constructor parameter list
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } Class data member initialization list
10.3.2 Implementing a derived class The syntax for the constructor of derived class is DClass :: DClass ( Plist ) : BClass ( Plist ) , DMbrList { // Body of derived class constructor … } • First base class • Second class data member • Last derived class
// Example13-1 #include < iostream.h > class Base { public : Base ( ) { cout << "\nBase created.\n" ; } } ; class D_class : public Base { public : D_class ( ) { cout << "D_class created.\n" ; } } ; void main () { D_class d1 ; } Base created. D_class created. Output
// Example13-2 #include <iostream.h> class parent_class { int private1 , private2 ; public : parent_class ( int p1 , int p2 ) { private1 = p1; private2 = p2; } int inc1 ( ) { return ++private1; } int inc2 ( ) { return ++private2 ; } void display ( ) { cout << "private1=" << private1 << " , private2=" << private2 << endl ; } }; Base class constructor parameter list
class derived_class : private parent_class { int private3 ; parent_class private4 ;// Class data member public: derived_class ( int p1 , int p2 , int p3 , int p4 , int p5 ) : parent_class ( p1 , p2 ) , private4 ( p3 , p4 ) { private3 = p5 ; } int inc1 ( ) { return parent_class :: inc1 ( ) ; } int inc3 ( ) { return ++private3 ; } void display ( ) { parent_class :: display ( ) ; private4 . display ( ); cout << "private3=" << private3 << endl ; } } ; void main ( ) { derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; } Five parameters of derived class constructor
class derived_class : private parent_class { int private3 ; parent_class private4 ;// Class data member public: derived_class( int p1 , int p2 , int p3 , int p4 , int p5 ) : parent_class ( p1 , p2 ) , private4 ( p3 , p4 ) { private3 = p5 ; } int inc1 ( ) { return parent_class :: inc1 ( ) ; } int inc3 ( ) { return ++private3 ; } void display ( ) { parent_class :: display ( ) ; private4 . display ( ) ; cout << "private3=" << private3 << endl ; } } ; void main ( ) { derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; } For base class parent_class(p1,p2) Initialize private1 and private2
class derived_class : private parent_class { int private3 ; parent_class private4 ;// Class data member public: derived_class( int p1 , int p2 , int p3 , int p4 , int p5 ) : parent_class ( p1 , p2 ) , private4 ( p3 , p4 ) { private3 = p5 ; } int inc1 ( ) { return parent_class :: inc1 ( ) ; } int inc3 ( ) { return ++private3 ; } void display ( ) { parent_class :: display ( ) ; private4 . display ( ) ; cout << "private3=" << private3 << endl ; } } ; void main ( ) { derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; } For class member private4 parent_class(p1,p2) : initialize private4.private1 and private4.private2
class derived_class : private parent_class { int private3 ; parent_class private4 ;// Class data member public: derived_class( int p1 , int p2 , int p3 , int p4 ,int p5 ) : parent_class ( p1 , p2 ) , private4 ( p3 , p4 ) { private3 = p5 ; } int inc1 ( ) { return parent_class :: inc1 ( ) ; } int inc3 ( ) { return ++private3 ; } void display ( ) { parent_class :: display ( ) ; private4 . parent_class :: display ( ) ; cout << "private3=" << private3 << endl ; } } ; void main ( ) { derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; } For derived class Initialize data member private3
class derived_class : private parent_class { int private3 ; parent_class private4 ; // Class data member public: derived_class( int p1 , int p2 , int p3 , int p4 ,int p5 ) : parent_class ( p1 , p2 ) , private4 ( p3 , p4 ) { private3 = p5 ; } int inc1 ( ) { return parent_class :: inc1 ( ) ; } int inc3 ( ) { return ++private3 ; } void display ( ) { parent_class :: display ( ) ; private4 . parent_class :: display ( ) ; cout << "private3=" << private3 << endl ; } } ; void main ( ) { derived_class d1 ( 17 , 18 , 1 , 2 , -5 ) ; d1 . inc1 ( ) ; d1 . display ( ) ; } Output private1 = 18 , private2 = 18 private1 = 1 , private2 = 2 private3 = -5
10.4 PROTECTED MEMBERS AND INHERITANCE保护成员与继承 • Data members and member functions can be cover in the derived class. • The derived class member functions do not access to the private member • of base class.
Example class base { public : int a ,b ; }; class derived : public base { public : int b , c ; } ; void f ( ) { derived d ; d . a = 1 ; d . base :: b = 2 ; // use member b of base class d .b = 3 ; // use member b of derivedclass d . c = 4 ; };
Example class X { public : void get_ij ( ) ; void put_ij ( ) ; private : int i , j ; }; class Y : public X { public : int get_k ( ) ; void make_k ( ) ; private : int k ; }; void Y :: make_k ( ) ; { k = i * j ; // illegal } ;
Example class X { public : void get_ij ( ) ; void put_ij ( ) ; private : int i , j ; }; class Y : public X { public : int get_k ( ) ; void make_k ( ) ; private : int k ; }; void Y :: make_k ( ) ; { k = i * j ; // illegal } ; protected : int i , j ; k = i * j ; // legal
10.5 CONTROLLING INHERITANCE 控制继承 10.5.1 Public Inheritance 公有继承 class DerivedClass : public BaseClass { public : // public section … private : // private section … } ; The public members and protected members keep their character in derived class.
class X class Y class Z // Example13-3 #include<iostream.h> class X { public : void get_ij( ) { cout << "Enter two numbers:" ; cin >> i >> j ; }; void put_ij( ) { cout << i << " " << j << '\n' ; }; protected : int i , j ; }; class Y : public X { public : int get_k( ) { return k ; }; void make_k( ) { k = i * j; }; // use base class DM private : int k ; }; class Z : public Y { public : void f( ) { i= 2 ; j= 3; }; // use base class DM }; void main ( ) { Y var1; Z var2 ; var1.get_ij( ) ; var1.put_ij( ) ; var1.make_k( ) ; var2.f( ) ; var2.put_ij( ) ; }
10.5.2 Private inheritance 私有继承 class DerivedClass : private BaseClass { public : // public section … private : // private section … } ; The public members and protected members of base class are private member in derived class.
// Example13-4 #include<iostream.h> class X { public : void get_ij( ) { cout << "Enter two numbers:" ; cin >> i >> j ; }; void put_ij( ) { cout << i << " " << j << '\n' ; }; protected : int i , j ; }; class Y : public X { public : int get_k( ) { return k ; }; void make_k( ) { k = i * j; }; // use base class DM private : int k ; }; class Z : public Y { public : void f( ) { i= 2 ; j= 3; }; // use base class DM }; void main ( ) { Y var1; Z var2 ; var1.get_ij( ) ; var1.put_ij( ) ; var1.make_k( ) ; var2.f( ) ; var2.put_ij( ) ; }
class X private class Y public class Z // Example13-4 #include<iostream.h> class X { public : void get_ij( ) { cout << "Enter two numbers:" ; cin >> i >> j ; }; void put_ij( ) { cout << i << " " << j << '\n' ; }; protected : int i , j ; }; class Y : private X { public : int get_k( ) { return k ; }; void make_k( ) { k = i * j; }; // use base class DM private : int k ; }; class Z : public Y { public : void f( ) { i= 2 ; j= 3; }; // use base class DM }; void main ( ) { Y var1; Z var2 ; var1.get_ij( ) ; var1.put_ij( ) ; var1.make_k( ) ; var2.f( ) ; var2.put_ij( ) ; } OK i, j are private member in Y class
class X private class Y public class Z // Example13-4 #include<iostream.h> class X { public : void get_ij( ) { cout << "Enter two numbers:" ; cin >> i >> j ; }; void put_ij( ) { cout << i << " " << j << '\n' ; }; protected : int i , j ; }; class Y : private X { public : int get_k( ) { return k ; }; void make_k( ) { k = i * j; }; // use base class DM private : int k ; }; class Z : public Y { public : void f( ) { i= 2 ; j= 3; }; // use base class DM }; void main ( ) { Y var1; Z var2 ; var1.get_ij( ) ; var1.put_ij( ) ; var1.make_k( ) ; var2.f( ) ; var2.put_ij( ) ; } Illegal Can not access private member of base class
class X private class Y public class Z // Example13-4 #include<iostream.h> class X { public : void get_ij( ) { cout << "Enter two numbers:" ; cin >> i >> j ; }; void put_ij( ) { cout << i << " " << j << '\n' ; }; protected : int i , j ; }; class Y : private X { public : int get_k( ) { return k ; }; void make_k( ) { k = i * j; }; // use base class DM private : int k ; }; class Z : public Y { public : void f( ) { i= 2 ; j= 3; }; // use base class DM }; void main ( ) { Y var1; Z var2 ; var1.get_ij( ) ; var1.put_ij( ) ; var1.make_k( ) ; var2.f( ) ; var2.put_ij( ) ; } Illegal main() can not call private MF of any objects
10.5.3 Protected inheritance 保护继承 class DerivedClass : protected BaseClass { public : // public section … private : // private section … } ; The public members and protected members of base class are protected member in derived class. Protected inheritance is used rarely.
Derived Derived class B : public A class C : private A Common functions Such as : main() Do you know how access x, y and z public : x class A protected : y private : z
class A class B 10.6 MULTIPLE INHERITANCE 多继承 A derived class can inherit from two or more base class. class C : public A ,public B
10.6 MULTIPLE INHERITANCE 多继承 A derived class can inherit from two or more base class. The syntax for declaring a class derived using multiple inheritance is classDClass: publicBClass, publicBClass{ public : // public section … private : // private section … } ;
class A class B class C // Example13-4 #include<iostream.h> class A { public : void setA ( int x ) { a = x ; } ; void showA( ) { cout << a << endl ; } ; private : int a ; } ; class B { public : void setB ( int x ) { b = x ; } ; void showB ( ) { cout << b << endl ; } ; private : int b ; } ; class C : public A , private B { public : void setC ( int x , int y , int z ) { setA ( x ) ; setB ( y ) ; c = z ; } ; void showC ( ) { showA ( ) ; showB ( ) ; cout << c << endl ; } ; private : int c ; } ; void main ( ) { C obj ; obj . setA ( 5 ) ; obj . showA ( ) ; obj . setC ( 6 , 7 , 9 ) ; obj . showC ( ) ; //obj . setB ( 6 ) ; // error, private inheritance //obj . showB ( ) ;// error }
10.7 VIRTUAL BASE CLASS • If a derived class be derived from multiple base classes, and these base • have a common base class, then, when access members of this common • base class may be open to different interpretations.
class B { b } class B { b } Example class B { public : int b ;} ; class B1 : public B { private : int b1 ; } ; class B2 : public B { private : int b2 ; } ; class C : public B1 , public B2 { public : int f ( ) ; private : int d ; } ; class B1 { b1 } class B2 {b2} class C { f () , d } … C c ; c . b// error c . B :: b // error,where from? c . B1 :: b // ok,from B1 c . B2 :: b // ok ,from B2
class B { b } class B { b } class B1 { b1 } class B2 {b2} class C { f () , d } // Example13-5 #include<iostream.h> class B{public: int b;}; class B1:public B {public: int b1;}; class B2:public B {public: int b2;}; class C:public B1, public B2 {public: f(); private: int b1;}; void main() { C c; c.B1::b=5; c.B2::b=10; cout<<"path B1==>"<<c.B1::b<<endl; cout<<"path B2==>"<<c.B2::b<<endl; } Output: path B1==> 5 path B2==> 10
class B { b } class B { b } class B1 { b1 } class B2 {b2} class C { f () , d } b b1 B b B1 b2 B C d B2 Example class B { public : int b ;} ; class B1 : public B { private : int b1 ; } ; class B2 : public B { private : int b2 ; } ; class C : public B1 , public B2 { public : int f ( ) ; private : int d ; } ; Store of multiple derived class object C When create object C, constructor of B is called two times. Once for B1, Others for B2. A C object contains two sub-object of B.
10.7 VIRTUAL BASE CLASS • If a derived class be derived from multiple base classes, and these base • have a common base class, then, when access members of this common • base class may be open to different interpretations. • For produce only one sub-object in deriver class object, the base classes must be declared virtual inheritance the common base class. Key word virtual
class B1 { b1} class B2 {b2} Example class B { public : int b ;} ; class B1 : virtual public B { private : int b1 ; } ; class B2 : virtual public B { private : int b2 ; } ; class C : public B1 , public B2 { private : float d ; } ; class B { b } As: C cc ; cc . b// OK class C { d } cc . B1 :: b and cc . B2 :: b is same sub-object of class B
class B { b } class B1 { b1} class B2 {b2} class C { d } b1 B1 C b2 B2 d b B Example class B { public : int b ;} ; class B1 : virtual public B { private : int b1 ; } ; class B2 : virtual public B { private : int b2 ; } ; class C : public B1 , public B2 { private : float d ; } ; Store of object C using virtual inheritance
10.7 VIRTUAL BASE CLASS • If a derived class be derived from multiple base classes, and these base • have a common base class, then, when access members of this common • base class may be open to different interpretations. • For produce only one sub-object in deriver class object, the base classes must be declared virtual inheritance the common base class. • Using virtual inheritance, the constructor of common base class is called only once.
// Example13-6 #include < iostream.h > class A { public : A ( ) { cout << "class A" << endl ; } } ; class B : virtual public A { public : B ( ) {cout << "class B" << endl ; } } ; class C : virtual public A { public : C ( ) {cout << "class C" << endl ; } } ; class D : public B , public C { public : D ( ) {cout << "class D" << endl ; } } ; void main ( ) { D dd ; } class A class B class C class D Output