继承,虚函数与多态,以及对图书管理系统的总结

1.派生类的声明方式:

class  派生类名:[继承方式]  基类名

     派生类新增加的成员

};

继承方式包括: public (公用的),private(私有的),protected(受保护的),继承方式是可选的如果不写默认为私有的。

1. 公有继承(public)

公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。

2. 私有继承(private)

私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。

3. 保护继承(protected)

保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。

2.代码示例
#include<iostream>
#include<string>
using namespace std;
class Student
{
public :
    Student(string s, int g,int a)
    {
        cout << "Constuct Student" << endl;
        name = s;
        grade = g;
        age = a;
    }
    void print()
    {
        cout << "Student:" << endl;
        cout << "name=" << name << endl;
        cout << "grade=" << grade<<endl;
        cout << "age=" << age << endl;
    }
protected:     //保护型子类可以直接调用。
    string name;
    int grade;
private:     //注意这是私有的子类不能直接用。
    int age;
};

class GraduateStudent :public Student                        //继承方式为public 表示公有继承
{
public:
    GraduateStudent(string s, int g, int a) :Student(s, g, a)   //调用基类的构造函数,构造基类
    {
        cout << "Constuct GraduateStudent" << endl;
    } 
    /*
    公有继承方式,会把基类的公有成员(变量和函数)继承到子类公有成员,保护成员
    变成基类的保护成员,但是私有成员子类也一样不可以访问
    */
    void print1()
    {
        cout << "GraduateStudent:" << endl;                           
        cout << "name= " << name << endl;
        cout << "grade= " << grade << endl;   //因为基类中name为private类型所以不能在子类中直接用。
    }

};

void main()
{
    GraduateStudent g("Ouyang", 95, 21);
    g.print();                     //基类成员为protected保护类型子类可以直接访问基类公共成员成员
    g.print1();
    system("pause");
}
注意:
- 基类的私有成员,子类不可以访问
- 基类的保护成员,子类可以继承为自己的保护成员。在派生类可以访问,在外部不可以访问。
- 基类的公有成员,子类可以继承为自己的公有成员。在派生类可以访问,在外部也可以访问。

私有继承(private)
私有继承方式的,就是在继承时,把protected变成private,它需要注意的事项为:

(1) 基类公有成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(2). 基类保护成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(3) 基类私有成员,子类一样不可以访问基类的私有成员,

3.虚函数与多态
冠以关键字virtual的成员函数成为虚函数。

虚函数,它允许函数调用与函数体之间的联系在运行时才建立,即在运行时才决定如何动作。虚函数声明的格式:

  virtual 返回类型 函数名(形参表)

  {

    函数体

  }

代码示例如下:

#include<iostream>
#include<string>
using namespace std;
class Student
{
    public:
    Base(char xx){x=xx;}
    virtual void who(){cout<<"Base class:"<<x<<ensl;}//  此处定义了虚函数。
    protected:
    char y;
};
class First_:public Base
{
    public:  first_d(char xx,char yy):Base(xx){y=yy;}
    protected: char y;
};
class Second_d:public First_d
{
    public:
    Second(char xx,char yy,charzz):First_d(xx,yy){z=zz;}
    void who(){cout<<"Second derived class:"<<x<<y<<z<<endl;}
    protected: char z;
};
int main()
{
    Base B_obj('A');First_d F_obj('T','O');Second_d S_obj('E','N','D');
    Base *p;
    p=&B_obj; p-<>who();
     p=&F_obj; p-<>who();
      p=&S_obj; p-<>who();
}

纯虚函数

1,纯虚函数是一个在基类中说明的虚函数,在基类中没有定义, 要求任何派生类都定义自己的版本

2,纯虚函数为各派生类提供一个公共界面

3 纯虚函数说明形式:

         virtual 类型  函数名(参数表)= 0 ;,

4, 一个具有纯虚函数的基类称为抽象类。

例如:

class point { /*……*/ } ;

class shape           // 抽象类

{ point center ;

     ……

 public :

 point  where ( ) { return  center ; }

 void  move ( point p ) {center = p; draw ( ) ; }

  virtual  void rotate ( int ) = 0 ;               //纯虚函数

  virtual  void draw ( ) = 0 ;               // 纯虚函数

} ;

注意:
4.如果一个类中至少有一个纯虚函数,那么就称该类为抽象类。所以上述中Graph类就是抽象类。对于抽象类有以下几个注意点:(1)抽象类只能作为其他类的基类来使用,不能建立抽象类对象;(2)不允许从具体类中派生出抽象类(不包含纯虚函数的普通类);(3)抽象类不能用作函数的参数类型、返回类型和显示转化类型;(4)如果派生类中没有定义纯虚函数的实现,而只是继承成了基类的纯虚函数。那么该派生类仍然为抽象类。一旦给出了对基类中虚函数的实现,那么派生类就不是抽象类了,而是可以建立对象的具体类;
虚析构函数
C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。
示例如下
现有Base基类,其析构函数为非虚析构函数。Derived1和Derived2为Base的派生类,这两个派生类中均有以string* 指向存储其name的地址空间,name对象是通过new创建在堆上的对象,因此在析构时,需要显式调用delete删除指针归还内存,否则就会造成内存泄漏。

class Base {   public:  ~Base() {    cout << "~Base()" << endl;  }  }; 

 class Derived1 : public Base {   public:    Derived1():name_(new string("NULL")) {}

    Derived1(const string& n):name_(new string(n)) {}

     ~Derived1() {      delete name_;      cout << "~Derived1(): name_ has been deleted." << endl;    }     private:    string* name_;  };

  

  class Derived2 : public Base

 {   public:    Derived2():name_(new string("NULL")) {}   

 Derived2(const string& n):name_(new string(n)) {}

     ~Derived2() {      delete name_;      cout << "~Derived2(): name_ has been deleted." << endl;    }     private:    string* name_;  };  

int main() {
  Derived1* d1 = new Derived1();
  Derived2 d2 = Derived2("Bob");
  delete d1;
  return 0;
}

d1为Derived1类的指针,它指向一个在堆上创建的Derived1的对象;d2为一个在栈上创建的对象。其中d1所指的对象需要我们显式的用delete调用其析构函数;d2对象在其生命周期结束时,系统会自动调用其析构函数。

4.图书管理系统分析

(1).添加图书时跟着记录;
istream&operator>>(istream&is,Book&b)
{   b.v.clear();
    Recordt h;
    int i;
    is>>b.shuhao;
    if(b.shuhao=="end")return is;
   is>>b.shuming>>b.zuozhe>>b.chuban>>b.place>>b.zong>>b.yijie>>b.count;
     for(int j=1;j<=b.count;j++)//这位同学所借的书 .
    {
        is>>h;
       b.v.push_back(h);
       i=b.v.size();
      b.b1.insert(make_pair(h.getXuehao(),i-1));
    }
    return is;
}
同理,添加学生时也跟着记录;
istream&operator>>(istream&is,Student&b)
{   b.v.clear();
    Records h;
    int i;
    is>>b.name;
    if(b.name=="end")return is;
    is>>b.xuehao>>b.zhuanye>>b.banji>>b.zong>>b.yijie>>b.count;
     for(int j=1;j<=b.count;j++)//这位同学所借的书 .
    {
        is>>h;
       b.v.push_back(h);
       i=b.v.size();
      b.b1.insert(make_pair(h.getShuming(),i-1));
    }
    return is;
}
管理员,可以对书,对学生操作,进行增删查改,
按出版社查找。
void serchbyplace(string s)
{
    it=find_if(v1.begin(),v1.end(),cmp1(s));
    while(it!=v1.end())
    {
        cout<<(*it);
        it=find_if(it+1,v1.end(),cmp1(s));
    }
}
按书名查找
  void serchbyshuming(string sm)
  {
      mit1=b1.find(sm);
        it=v1.begin()+mit1->second;
        cout<<(*it);
  }
按出版时间
void serchbytime(Time a,Time b)
    {
        for(it=v1.begin();it!=v1.end();it++)
        {
            if(a<(*it).getChuban()&&(*it).getChuban()<b)
            {
                cout<<(*it);
            }
        }
    }
void xujie(string sm,string xue)//学生续借,输入书名,学号。续借后的信息并且更新。
    {
        mit1=b1.find(sm);
        it=v1.begin()+mit1->second;
        (*it).yanchi(xue);
    }
    void addjilu(string sm,Recordt y)//这本书被人借了,在这本书后面添加借书人信息。
    {
       mit1=b1.find(sm);
        it=v1.begin()+mit1->second;
        (*it).addRecordt(y);
    }
    void shangjia(Book b)//新书上架。
    {
       v1.push_back(b);
         int i=v1.size();
             b1.insert(make_pair(b.getShuming(),i-1));
             b2.insert(make_pair(b.getShuhao(),i-1));
             b3.insert(make_pair(b.getChuban(),i-1));
    }
    void xiajia(string sm)//旧书下架,。。
    { mit1=b1.find(sm);
        b1.erase(b1.find(sm));
      it=v1.begin()+mit1->second;
      v1.erase(it);
    }
    void benshu(string sm,int i)  //输入书名,和这本书新买的本书,并及时更新。
    {
        mit1=b1.find(sm);
        it=v1.begin()+mit1->second;
        (*it).setZong(i);
    }
    void guihuan(string sm,string xue)   //学生还书,消除记录并及时更新。
    {
        mit1=b1.find(sm);
        it=v1.begin()+mit1->second;
        (*it).shanchu(xue);

    }

图书管理的总结:

学生  ,借书,查书,还书,续借,直接调用管理员,通过管理员来实现,并重新写入。

下面介绍一下,添加学生和图书(包含记录)

(1)先写一个图书记录类,(Recordt),用于记录每本书所借的学生同样(Records),用于记录每个同学所借的书。

(2)在class BOOK和Class Student两个类中定义两个容器分别为vector<Recordt>和vector<Records>.

(3)分别重载输入运算符,以添加图书为例,先输入这本书的信息,书号,。。。。。借书本数。定义一个for循环从一到借书本数添加Recordt。

不足:学生登录写的过于复杂,输入的信息有点冗杂。不是直接输入学号进行登录。还要输入专业班级。
    心得体会
类的继承,在程序设计中本人感觉,用处还是非常多的,他可以简化程序,不让程序那么冗杂,让程序看起来更加的清晰。首先我们要先找到类中相同的部分,直接继承即可,但要注意基类的变量要定义为保护型的,以图书管理系统为例,图书管理员和学生的功能有相同的部分,如各种查书的功能,这样学生就可以直接从管理员那里继承这些功能,起到简化程序的作用。

C++支持多态性。所谓多态性是指:通过继承而相关的不同的类,它们的对象能够对同一个函数调用做出不同的响应。

  多态性是通过虚函数实现的。

   当通过基类指针请求使用虚函数时,C++会在与对象关联的派生类中正确的选择重定义的函数。

   使用虚函数和多态性能够使成员函数的调用根据收到该调用的对象的类型产生不同的动作。

    尽管不能实例化抽象基类的对象,但是可以声明抽象基类的指针。当实例化了具体类的对象后,可以用这种指针使派生类对象具有多态性操作能力。

虚函数前面一定要加上关键字virtual。本人感觉虚函数还是有点不太好理解,课下会多浏览一下这方面的博客。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


猜你喜欢

转载自blog.csdn.net/qq_40859951/article/details/80781108
今日推荐