继承  Inherit
   
C++中可重用性
父类 基类
继承 派生
子类 派生类
C++通过继承关系,实现了代码的可重用性。
#include <iostream>
using namespace std;
class Human    //父类  共性
{
public:
    void eat(string food)
    {
        cout<<"i am eating"<<food<<endl;
    }
};
//public 继承方式
class Teacher:public Human  //  子类在父类的基础上增加了新的功能,体现的是个性
{
//访问权限
public:
    void tech(string course)
    {
        cout<<"i am a teacher teach "<<course<<endl;
    }
};
class Student:public Human
{
public:
    void study(string course)
    {
        cout<<"i am a student learning "<<course<<endl;
    }
};
int main()
{
    Teacher t;
    t.tech("ttttt");
    Student s;
    s.eat("aaa");
    s.study("c++");
    return 0;
}组合是聚合关系
属于是继承关系
public 继承方式没有影响子类成员的访问方式,影响了父类中的成员在子类中的访问方式
父类中 pub pro pri
子类public继承 public protected inaccess
1、继承后全盘接受,除了析构器和构造器。基类会造成派生类的成员冗余,因此积累是需要设计的。
2、派生类有自己的个性,使派生类有了意义。
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
    Student(string sn, int ia, float fs)
    {
    }
    void dis();    
private:
    string name;
    int age;
    float score;
};
#endif  //STUDENT_Hstudent.cpp
#include "student.h"
#include <iostream>
Student::Student(string sn, int ia, float fs)
    :name(sn),age(ia),score(fs)
{
}
void Student::dis()
{
    cout<<"name: "<<name<<endl;
    cout<<"age: "<<age<<endl;
    cout<<"score: "<<score<<endl;
}main.cpp
#include <iostream>
#include "student.h"
#include "gradient.h"
#include "doctor.h"
using namespace std;
int main()
{
    Student s("aa", 30, 100);
    s.dis();
    cout<<"----------"<<endl;
    Graduate g("ggg", 50, 90, 1000);
    g.print();
    Doctor d("ddd", 23, 200, 5000, "doc");
    d.dump();
    return 0;
}Graduate.h
#ifndef GRADUATE_H
#define GRADUATE_H
#include "student.h"
class Graduate:public Student
{
public:
    Graduate(string sn, int ia, float fs, double ds);
    void print();
private:
    double salary;
};
#endif  //GRADUATE_Hgradient.cpp
#include "gradient.h"
Gradient::Gradient(string sn, int ia, float fs, double ds)
    :Student(sn, ia, fs),salary(ds)
{
    //inaccess
    // name = sn;
    // age = ia;
    // score = fs;
}
void Gradient::print()
{
    dis();  // name age score 不可见,dis()可用
    cout<<"salary: "<<salary<<endl;
}父类中如果有标配,重载或默认,把默认包含进来
子类中可以不用显式的调用父类的构造器
Doctor.h
#ifndef DOCTOR_H
#define DOCTOR_H
#include "gradient.h"
class Doctor:public Gradient
{
public:
    Doctor(string sn, int ia, float fs, double ds, string st);
    void dump()
    {
        print();
        cout<<"title: "<<title<<endl;
    }
private:
    string title;
};
#endif  //DOCTOR_Hdoctor.cpp
#include "doctor.h"
Doctor::Doctor(string sn, int ia, float fs, double ds, string st)
    :Gradient(sn,ia,fs,ds),title(st)
{
}子类只需对父类负责,不需要对父类的父类负责
类中的子对象 int age, float salary
初始化顺序:父类初始化(父类的父类初始化)、类对象初始化、子类初始化
子类未实现拷贝构造时,会调用父类的拷贝构造器(无论是否实现)
子类一旦实现拷贝构造,则必须显式的调用父类的拷贝构造器
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
public:
    Student(string sn, int ia, float fs):
    void dis();
    Student(const Student& another);  // 构造器
    Student & operator = (const Student & another);
private:
    string name;
    int age;
    float score;
};
#endif#include "student.h"
#include <iostream>
using namespace std;
Student::Student(string sn, int ia, float fs)
    :name(sn),age(ia),score(fs)
{
    
}
void Student::dis()
{
    cout<<"name: "<<name<<endl;
    cout<<"age: "<<age<<endl;
    cout<<"score: "<<score<<endl;
}
//定义构造器
Student::Student(const Student& another)
{
    this->name = another.name;
    this->age = another.age;
    this->score= another.score;
}
Student & Student::operator = (const Student & another)
{
    if(this == &another)
        return *this;
    this->name = another.name;
    this->age = another.age;
    this->score = another.score;
    return *this;
}#ifndef GRADIENT_H
#define GRADIENT_H
#include "student.h"
class Gradient
{
public:
    Gradient(string sn, int ia, float fs, double ds);
    void print();
    Gradient(const & another);  // 构造器
    Gradient & another = (const Gradient & another);
private:
    double salary;
};
#endif#include "gradient.h"
#include <iostream>
using namespace std;
Gradient::Gradient(string sn, int ia, float fs, double ds)
    :Student(sn, ia, fs),salary(ds)
{
    
}
void Gradient::print()
{
    dis();
    cout<<"salary: "<<salary<<endl;
}
Gradient::Gradient(const Gradient& another)
    :Student(another),salary(another.salary)
{
    // Student(another);  // 赋值兼容(子类对象(引用或指针),可以赋值给父类(引用或指针))
    // this->salary = another.salary;
}
Gradient & Gradient::operator = (const Gradient & another)
{
}
#include <iostream>
#include "student.h"
#include "gradient.h"
using namespace std;
int main()
{
    Student s("aa", 200, 100);
    s.dis();
    cout<<"---------"<<endl;
    Gradinet g("gg", 100, 500);
    g.print();
    return 0;
}子类中未实现赋值重载时,会调用父类的赋值重载
子类一旦实现赋值重载,不会主动调用父类的赋值重载
子类中会把父类重名的成员shadow
overload 重载:同一作用域,函数名相同,参数列表不同(个数、类型、顺序) 希望发生
shadow 覆盖:父子类中,只要函数名相同即构成shadow 不希望发生
继承方式
| 成员/继承方式 | public | protected | private | 
| public | public | protected | private | 
| protected | protected | protected | inaccessable | 
| private | inaccessable | inaccessable | inaccessable | 
类内部的private protected public 影响访问权限
在继承中,private protected public 父类中的成员在子类中的访问权限
1、在子类中 2、在子类对象中
virtual
从诸多父类中提取公因式,把相同的类成员提到祖父类中,分别令父类虚继承祖父类,子类正常继承自父类,此时子类中无冗余信息,访问亦方便。
#include <iostream>
using namespace std;
class M
{
public:
    M(int m):a(m){}
protected:
    int a;
};
class A:virtual public M
{
public:
    A(int i):M(i){}
};
class B:virtual public M
{
public:
    B(int j):M(j){}
};
class C:public A, public B
{
public:
    C(int m):A(m), B(m), M(m){}
    void func()
    {
        cout<<a<<endl;
    }
};
int main()
{
    C c(100);
    c.func();
    return 0;
}
    
     虚继承
    
   
class A: virtual public M
虚基类需要设计和抽象,虚继承是一种继承的扩展
class A
{
    A(int i)
    {}
};
class B:virtual public A
{
    B(int n):A(n){}
};
class C:virtual public A
{
    C(int n):A(n){}
};
class D:public B, public C
{
    D(int n)
        :A(n), B(n), C(n)
    {}
}; 
