zoukankan      html  css  js  c++  java
  • 第十二章 继承

    第十二章 继承

    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<<"父亲的大房子我可以享受
    ";}
     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<<”人可以直立行走 ”;}};

                       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的无参构造
    ";}
    23     father(int m,int n){a=m;pa=n;cout<<"father的有参构造"<<a<<" "<<pa<<endl;}
    24     ~father(){cout<<"father的析构
    ";}
    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的无参构造
    ";}
    35     son(int x,int y,int z,int t);
    36     //派生类中初始化基类构造函数(有优势)
    37     //不初始化就会调用father的无参构造函数    
    38     ~son(){cout<<"son的析构
    ";}
    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 }
  • 相关阅读:
    Linux常用命令(二)
    C#异步调用
    Ajax运用总结
    SQL Server2005 FOR XML PATH 语句的应用
    SQL Server 2005 处理交叉表
    如何控制并发和控制死锁(内含pb的处理要点)
    WPF 中的换行符
    C#委托的异步调用
    pivot 附近有语法错误,您可能需要将当前数据库的兼容级别设置为更高的值。
    应用系统BUG分布小结
  • 原文地址:https://www.cnblogs.com/zenseven/p/3735028.html
Copyright © 2011-2022 走看看