第十二章 继承

第十二章 继承

1.  什么是继承和派生?

继承:通常把子类不加修改的延续父类的特征,我们把它叫做继承

派生:子类在延续父类特征的基础上有添加了自己的新特征(这个过程叫做类的派生)

基类(父类),派生类(子类)   

2.  复杂的继承和派生.

3.  继承和派生如何在C++中实现.

 class son:public father

4.  单一继承.

在实际应用中可以将 基类和派生类视为一个整体

5.  保护成员.

类的私有成员只能被该类的公有成员友元所访问

 1 //友元函数
 2 #include "iostream"
 3 using namespace std;
 4 
 5 class Point
 6 {
 7 public:
 8     Point(double xx, double yy) { x=xx; y=yy; }
 9     void Getxy();
10     friend double Distance(Point &a, Point &b);//友元函数在类中声明
11 private:
12     double x, y;
13 };
14 
15 void Point::Getxy()
16 {
17     cout<<"("<<","<<")"<<endl;
18 }
19 //计算两点之间的距离
20 double Distance(Point &a, Point &b)//不同于类成员函数,友元函数无需类的属性
21 {
22     double dx = a.x - b.x;//可以直接调用类的私有成员
23     double dy = a.y - b.y;
24     return sqrt(dx*dx+dy*dy);
25 }
 1 //友元类 友元类的所有成员函数都是另一个类的友元函数
 2 #include"iostream"
 3 using namespace std;
 4 //class Girl;
 5 class Girl
 6 {
 7 private:
 8     char *name;
 9     int age;
10     friend class Boy;//声明位置:公有私有均可,常写为私有(把类看成一个变量)
11 public:
12     Girl(int x)
13     {
14         age = x; name = new char[6];//也可以直接放到栈中 name = "Smili";
15      //memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。
16         //memset(name,0,6);不这样做就会出错//int a[5];memset(a,1,5);//这里错了改成memset(a,1,5 *sizeof(int))就可以了最后一个参数是字节,而char只有一个字节
17         //memcpy(name,"Smili",5);
18         strcpy(name,"Smili");//拷贝了6个字符
19     }//这里怎么加全名Smili???
20     ~Girl(){delete []name;name = NULL;}
21 };
22 class Boy
23 {
24 public:
25     void disp(Girl &);
26 };
27 void Boy::disp(Girl &r){cout<<"girl's name is:"<<r.name<<",age:"<<r.age<<endl;}//此处体现了友元类的作用
28 int main()
29 {
30     Girl Smili(18);
31     Boy Joy;
32     Joy.disp(Smili);
33     return 0;
34 }

private体现了封装的含义:

派生类的成员不能直接访问基类的私有成员,目的是为了防止私有成员被其他类调用时修改数据;

为了解决这个问题我们引进了protected。

派生类可以访问基类的protected成员(前提:公有派生)

6.  公有派生的公有成员.

子类可以直接调用

7.  公有派生的保护成员.

子类可以通过自己间接访问

 1 #include <iostream>
 2 using namespace std;
 3 class father
 4 {
 5 protected:
 6     void room(){cout<<"父亲的大房子我可以享受\n";}
 7 };
 8 class son:public father
 9 {
10 public:
11     void enjoy(){room();}
12 };
13 int main()
14 {
15     son a;
16     //a.room();
17     a.enjoy();
18     return 0;
19 }

8.  公有派生的私有成员.

子类只能通过父类间接访问

 

public:门开的人可以直接进,protected/private:门是锁的钥匙在自家类里,不可直接访问:门是锁的钥匙在别人类里。

9.  继承的赋值.

只能小的调用大的,父类调用子类

到底是类型转换还是赋值??????????????????

见程序12-3-1

10.  私有派生.

11.  多重继承. 

class son:public father,private mother

12.  继承的构造与析构.

//单一继承的构造顺序:先父类后子类

 class f:public e,public b,public c,public d,public a

//多重继承的构造顺序:e,b,c,d,a,f

13.  向基类构造函数传递参数.

 1 //在创建派生类对象时,对数据初始化
 2 #include<iostream>
 3 using namespace std;
 4 class father
 5 {
 6 public:
 7     father(int i){a=i;cout<<"构造基类a的值:"<<a<<endl;}
 8     ~father(){cout<<"析构基类a的值:"<<a<<endl;}
 9 private:
10     int a;
11 
12 };
13 class son:public father
14 {
15 public:
16     son(int i,int j,int k);
17     ~son(){cout<<"析构子类b的值:"<<b<<endl;}
18 private:
19     int b;
20     father age;
21 
22 };
23 //将父类放在花括号外定义,子类成员放在花括号内定义,增加代码的可读性
24 son::son(int i,int j,int k):father(i),age(j)//利用派生类构造函数初始化基类的构造函数
25 {
26     //age=j;出错要调用无参构造函数
27     b=k;
28     cout<<"构造子类b的值:"<<b<<endl;
29 }
30 void main()
31 {
32     son b(1,2,3);
33 }

14.  多重继承容易产生两义性.

产生原因: 当多个基类中有相同的函数, 用子类定义的类调用该函数时

解决方法:①子类中添加同名函数②添加作用域限定符Tom.father::human();③单一继承④虚基类virtual

9.  继承中的重载.

子类会屏蔽掉父类的同名函数,不论参数是否不同.

此时就要引用virtual。

本章总结:

1.  继承:***********************①

派生方式                            基类的访问限定                                 派生类中对基类成员的访问限定                                     主函数中访问派生类对象的基类成员

共有派生                            public                                                      public                                                                                          可以直接访问

                                       protected                                                 protected                                                                                    不可直接访问

                                       private                                                 不可直接访问                                                                              不可直接访问

私有派生                            public                                                      private                                                                                         不可直接访问

                                       protected                                                 private                                                                                         不可直接访问

                                       private                                                    不可直接访问                                                                              不可直接访问

public:门开的人可以直接进,protected/private:门是锁的钥匙在自家类里,不可直接访问:门是锁的钥匙在别人类里。

2.  继承的赋值:只能小的调用大的,父类调用子类(虚函数处有用,体现多态性)

Father        A;                                           A=B           √

Father        *f;                                          B=A           ×     //B.operator=(B       &r){}//r用A传,A填不满B

Son    B;                                                    f=&B         √

Son    *s;                                                  S=&A        ×     //S的范围大,要是移动的话,就超出A对象了。就会出错

3.  解决两义性的方法:

①子类中添加同名函数

②加作用域限定符class Son:class father,class mother{};    Son XiaoMing; XiaoMing.father::x();

③单一继承

④虚基类virtual

                   class human{public: stand(){cout<<”人可以直立行走\n”;}};

                   class father:virtual public human{public};

                   class mother:virtual public human{public};

                   class son:public father,pblic mother{public};

                   son XiaoMing;

                   XiaoMing.stand();

4.  继承的构造与析构

①单一继承的构造顺序:先父类后子类。(父类的构造函数,不论有无调用都要构造一遍)

②class f:public e,public b, public c

多重继承的构造顺序:e,b,c,f

5.  基类的构造函数,一般由派生类传递初始值。

派生类成员一般在{}内定义,用于增加代码的可读性。

Son::Son(int x, int y, int z, int t):Fobject(x,y){c=z;d=t;}

7.

  重载 覆盖  隐藏
共同点:  函数名相同 函数名相同 函数名相同
不同点: 

同类参数类型数量不同 

或 有无const 

不同类同参有基virtual 

不同类,同参,且无virtual

不同类,不同参(不论有无virtual) 

体现: 由函数调用(静态联编) 由函数调用取决于object(动态联编) 取决于pointer(不能体现多态性)
 1 /**
 2 1.继承:***********************①
 3 派生方式            基类的访问限定                派生类中对基类成员的访问限定                主函数中访问派生类对象的基类成员
 4 共有派生            public                        public                                       可以直接访问
 5 protected                      protected                                    不可直接访问
 6 private                       不可直接访问                                 不可直接访问
 7 私有派生            public                        private                                      不可直接访问
 8 protected                     private                                      不可直接访问
 9 private                       不可直接访问                                 不可直接访问
10 public门开的人可以直接进,protected/private门是锁的钥匙在自家类里,不可直接访问:门是锁的钥匙在别人类里。
11 
12 2.继承的赋值:只能小的调用大的,父类调用子类(虚函数处有用)
13 3.子类会屏蔽掉父类的同名重载函数(见word文档)**********************②
14 4.解决两义性的方法:①子类中添加同名函数②添加作用域限定符③单一继承④虚基类virtual(见word文档)**********************③
15 */
16 //
17 #include"iostream"
18 using namespace std;
19 class father
20 {
21 public:
22     father(){cout<<"father的无参构造\n";}
23     father(int m,int n){a=m;pa=n;cout<<"father的有参构造"<<a<<" "<<pa<<endl;}
24     ~father(){cout<<"father的析构\n";}
25 protected:
26     int pa;
27 private:
28     int a;
29 };
30 
31 class son:public father//class son:virtual public father 虚基类
32 {
33 public:
34     son(){cout<<"son的无参构造\n";}
35     son(int x,int y,int z,int t);
36     //派生类中初始化基类构造函数(有优势)
37     //不初始化就会调用father的无参构造函数    
38     ~son(){cout<<"son的析构\n";}
39 protected:
40     int pb;
41     father Fobject;
42 private:
43     int b
44 };
45 son::son(int x,int y,int z,int t):Fobject(x,y)
46 {pb=t;b=z;cout<<"son的有参构造"<<b<<" "<<pb<<endl;}
47 int main()
48 {
49     son Sobject(3,4,5,6);//为什么这里要调用无参的构造函数?
50     return 0;
51 }
posted @ 2014-05-18 11:59  击进的Cocos  阅读(230)  评论(0编辑  收藏  举报