C++(6) の継承

継承 継承

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 は public protected inaccess を継承します

 1. デストラクターとコンストラクターを除く、継承後のすべてを受け入れます。基本クラスを使用すると派生クラスのメンバーが冗長になるため、蓄積を設計する必要があります。

2. 派生クラスには独自の個性があり、それが派生クラスを意味のあるものにします。

学生.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_H

学生.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;
}

卒業生.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_H

グラデーション.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;
}

親クラスに標準構成、オーバーロード、またはデフォルトがある場合は、デフォルトを含めます。

サブクラスは親クラスのコンストラクターを明示的に呼び出す必要はありません。

ドクター・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_H

ドクター.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 のサブオブジェクト、浮動小数点給与

初期化順序:親クラスの初期化(親クラスの親クラスの初期化)、クラスオブジェクトの初期化、サブクラスの初期化

サブクラスがコピー構築を実装していない場合、親クラスのコピー コンストラクターが (実装されているかどうかに関係なく) 呼び出されます。

サブクラスがコピー構築を実装したら、親クラスのコピー コンストラクターを明示的に呼び出す必要があります。

#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;
}

代入オーバーロードがサブクラスに実装されていない場合、親クラスの代入オーバーロードが呼び出されます。

サブクラスが代入オーバーロードを実装すると、親クラスの代入オーバーロードを積極的に呼び出すことはなくなります。

サブクラスでは、親クラスと同じ名前のメンバーがシャドウされます。

overload オーバーロード: 同じスコープ、同じ関数名、異なるパラメータ リスト (数値、型、順序) が発生することを期待します。

シャドウ カバレッジ: 親クラスと子クラスでは、関数名が同じである限りシャドウが構成されますが、これは予期されていません。

継承

メンバー/継承 公共 保護された プライベート
公共 公共 保護された プライベート
保護された 保護された 保護された アクセスできない
プライベート アクセスできない アクセスできない アクセスできない

クラス内の private protected public はアクセス権に影響します

継承では、プライベートはサブクラスの親クラスのメンバーのパブリック アクセス権を保護します。

1. サブクラス内 2. サブクラス オブジェクト内   

バーチャル 

多数の親クラスから共通因子を抽出し、同じクラスのメンバーを祖父母クラスにそれぞれ言及し、親クラスは祖父母クラスを仮想継承し、サブクラスは親クラスを通常継承するようにします。このとき、冗長な情報はありません。サブクラスにもアクセスできるので便利です。

#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;
}

仮想継承

クラスA: 仮想パブリック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)
    {}
};

おすすめ

転載: blog.csdn.net/jiangyangll/article/details/132326744